在 Java 中检查 AEAD 密码中的标签和关联数据

Tho*_*mas 5 java aes aes-gcm

我需要使用 AEAD 在两个用户之间共享信息,其中一部分必须加密,一部分应以明文形式保存。

使用 AES/GCM 加密消息后,是否有 API 可以检查密文标签并访问关联数据?

更详细地说:

我使用 Java 7 和 bouncycastle 作为提供程序,并且我已成功使用相应的 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);
}
Run Code Online (Sandbox Code Playgroud)

然而,据我了解,AES/GCM 密文应该已经包含可能影响解密的参数(随机数和关联数据)。因此,我希望能够从密文中检索它们,而不是必须将它们与密文一起存储并将它们传递给解密函数。此外,我希望能够运行完整性检查(计算标签)并对关联数据运行一些检查,而不必完全解密消息。

是否有一个 API 可以实现这一点,但我可能错过了?

到目前为止,我已经检查过:

Maa*_*wes 1

没有隐式格式将 GCM 的所有输入数据存储在特定位置。Java API 已经有点奇怪了,因为它自动将标签放在末尾。这使得算法与Cipher类更加兼容,但原则上标签只需要与密文一起保存——在哪里并不重要。现在您遇到的问题是,您不知道 AAD 在哪里结束,密文在哪里开始。

因此,您可以做的就是创建自己的格式(也许您的 AAD 具有静态大小,因此您可以连接),或者可以使用预定义的容器格式。有一个互联网草案 指定了如何在加密消息语法 (CMS) 中使用这两种模式。然后,AAD 可以存储在经过身份验证的属性中,其中还应包括所需的参数(包括包含随机数的 IV)。

如果您感到自虐,您也可以尝试在 GCM 模式下使用 XML 加密,但要注意验证 XML 真实性方面的许多陷阱(例如,请注意您实际上正在验证要使用的数据)。

Bouncy Castle 似乎使用 GCM 提供对 CMS 的支持。