首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >AES-GCM加密解密疑点

AES-GCM加密解密疑点
EN

Cryptography用户
提问于 2016-10-03 17:24:33
回答 1查看 5.6K关注 0票数 2

我在我的项目中使用了AES-GCM模式,我有一些疑问。

代码语言:javascript
复制
public String encrypt(String plainText, String authenticationTag) throws GeneralSecurityException, IOException {
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
        final int blockSize = cipher.getBlockSize();
        SecretKey secretKey = readKeyFile(...);
        byte[] plainTextByte = plainText.trim().getBytes(Charset.forName("UTF-8"));
        byte[] ivBytes = generateIV();
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes));
        cipher.updateAAD(authenticationTag.getBytes(Charset.forName("UTF-8")));
        byte[] encryptedMessage = cipher.doFinal(plainTextByte);
        byte iv_and_encryptedMessage[] = concatIvAndCipher(ivBytes, encryptedMessage, blockSize);
        Base64.Encoder encoder = Base64.getEncoder().withoutPadding();
        String iv_and_encryptedText = encoder.encodeToString(iv_and_encryptedMessage);
        return iv_and_encryptedText;
    }

    public String decrypt(String iv_and_encryptedTextBase64, String authenticationTag)
            throws GeneralSecurityException, IOException {
        Cipher cipher = Cipher.getInstance(ALGORITHM_MODE_PADDING);
        final int blockSize = cipher.getBlockSize();
        Base64.Decoder decoder = Base64.getDecoder();
        byte[] iv_and_encryptedMessage = decoder.decode(iv_and_encryptedTextBase64.trim());
        byte[] ivBytes = extractIvFrom(iv_and_encryptedMessage, blockSize);
        byte[] encryptedTextBytes = extractEncryptedMessageFrom(iv_and_encryptedMessage, blockSize);
        SecretKey secretKey = readKeyFile(...);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(GCM_TAG_LENGTH, ivBytes));
        cipher.updateAAD(authenticationTag.getBytes(Charset.forName("UTF-8")));
        byte[] decryptedByte = cipher.doFinal(encryptedTextBytes);
        String decryptedMessage = new String(decryptedByte, Charset.forName("UTF-8"));
        return decryptedMessage;
    }

问题:

  1. 我使用GUID作为身份验证标记,它绑定到敏感信息所属的用户。加密的文本和标记存储在不同位置的单独数据库中。这样可以吗?
  2. 根据我所读到的,AES-GCM接受(纯文本、IV、密钥、关联数据)和输出(密码文本、身份验证标记)。关联数据和身份验证标记是否相同,因为在cipher.updateAAD(...)中传递相同值时,加密和解密的实现可以工作吗?加密后如何获得认证标签?
  3. 我应该使用Bouncy城堡而不是使用默认的Java实现吗?
  4. 如果要加密的数据是16字节,什么时候应该为enc/dec生成一个新的DEK?
  5. 所有德克的一位KEK大师?对于加密DEK,我应该使用相同的AES实现吗?如果没有,那该用什么呢?
EN

回答 1

Cryptography用户

回答已采纳

发布于 2016-10-03 18:32:45

1)我使用GUID作为身份验证标记,它绑定到敏感信息所属的用户。加密的文本和标记存储在不同位置的单独数据库中。这样可以吗?

您没有使用GUID作为身份验证标记,而是将其用作附加的经过身份验证的数据,这是可以的,特别是因为您已经共享了一个密钥。身份验证标记--当使用稍微受黑客攻击的Java时--在密文末尾输出。

2)根据我所读到的,AES-GCM接受(纯文本、IV、密钥、关联数据)和输出(密码文本、身份验证标记)。关联的数据和身份验证标记是否相同,因为当我在cipher.updateAAD(.)中传递相同的值时,加密和解密的实现可以工作吗?加密后如何获得认证标签?

不,看上面。如果您想获得身份验证标记,您可能希望将其从密码文本的末尾去掉。

3)我是否应该使用BouncyCastle而不是使用默认的Java实现。

除非您想放弃AES-NI和GCM优化。对于OpenJDK / Oracle提供的API中已经存在的实现,我将远离Benniy城堡。

4)如果要加密的数据为16字节,何时应该为enc/dec生成一个新的DEK。

请参阅NIST规范;一般来说,它取决于身份验证标记的大小,因此可能有多个答案。

不过,问题的代码中没有显示GCM_TAG_LENGTH的常量值,因此不清楚在特定情况下身份验证标记大小是多少。

在注释中提到了128位的身份验证标记大小。NIST规范对此并不完全清楚,因此我要求提供在这个问题上大小,这在很长时间后才得到了答复。

5)所有德克都有一位KEK大师?对于加密DEK,我应该使用相同的AES实现吗?如果没有,那该用什么呢?

这取决于协议以及最终的用例和威胁模型。但一般来说,我会使用KDF (如HKDF )来派生密钥,而不是包装(加密)密钥。为了达到这个目的,您可能需要使用Bouncy城堡,因为Java本身没有任何好的KDF实现。

票数 3
EN
页面原文内容由Cryptography提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://crypto.stackexchange.com/questions/40414

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档