我需要使用AEAD在两个用户之间共享信息,其中一部分必须加密,其中一部分应以明文形式保存。
在使用AES / GCM加密邮件后,是否有API检查密文标记并访问关联数据?
我使用带有bouncycastle的Java 7作为提供程序,我已成功使用相应的API成功加密和解密我的数据:
private byte[] encrypt(SecretKey key, byte[] nonce, byte[] message, byte[] associatedData) throws ... {
Cipher aeadCipher = Cipher.getInstance(AES_GCM_NOPADDING);
aeadCipher.init(Cipher.ENCRYPT_MODE, kint, new GCMParameterSpec(GCM_MAC_SIZE, nonce);
aeadCipher.updateAAD(associatedData);
return aeadCipher.doFinal(message);
}
private byte[] decrypt(SecretKey key, byte[] nonce, byte[] cipherText, byte[] associatedData) throws ... {
Cipher aeadCipher = Cipher.getInstance(AES_GCM_NOPADDING);
aeadCipher.init(Cipher.DECRYPT_MODE, kint, new GCMParameterSpec(GCM_MAC_SIZE, nonce);
aeadCipher.updateAAD(associatedData);
return aeadCipher.doFinal(cipherText);
}
但是,我的理解是AES / GCM密文应该已经包含可能影响解密的参数(nonce和associatedData)。 因此,我希望能够从密文中检索它们,而不是将它们与密文一起存储并将它们传递给解密函数。此外,我希望能够运行完整性检查(计算标记)并对相关数据运行一些检查,而不必完全解密消息。
是否有允许这样做的API以及我可能错过了?
到目前为止,我已经检查过:
答案 0 :(得分:0)
没有隐式格式将GCM的所有输入数据存储在特定位置。 Java API已经有点奇怪了
感觉它会自动将标签放在最后。这使得
算法与Cipher
类更兼容,但原则上只是标记
需要与密文保持一致 - 哪里无关紧要。现在你有了
例如,您不知道AAD在哪里结束并且密文开始的问题。
所以你要做的就是创建自己的格式(也许你的AAD有一个 静态大小,因此您可以只连接)或者您可以使用预定义的容器格式。 有一个internet draft 指定如何在加密消息语法(CMS)中使用这两种模式。 然后可以将AAD存储在经过身份验证的属性中,该属性还应包含所需的属性 参数(包括由nonce组成的IV)。
如果你觉得自虐,你也可以尝试在GCM模式下使用XML加密,但要注意验证XML真实性方面的许多缺陷(例如要注意你实际上在验证你要使用的数据)。 / p>
Bouncy Castle似乎使用GCM为CMS提供支持。
答案 1 :(得分:0)
由于Java API会自动将标记放在最后,您只需从加密结果中提取此标记,如下所示:
private byte[] getTag(SecretKey key, byte[] nonce, byte[] message, byte[] associatedData) throws ... {
Cipher aeadCipher = Cipher.getInstance(AES_GCM_NOPADDING);
aeadCipher.init(Cipher.ENCRYPT_MODE, kint, new GCMParameterSpec(GCM_MAC_SIZE, nonce);
aeadCipher.updateAAD(associatedData);
byte[] encrypted = aeadCipher.doFinal(message);
// Assuming you have an AAD_SIZE = 128 bits (16 bytes)
return Arrays.copyOfRange (encrypted, encrypted.length-16, encrypted.length)
}