如何在 Java 中使用 AAD 解密 AES-GCM 编码消息
我有一些现有的 C++ 代码,它们使用 openssl 发送加密消息。
我正在编写一个新的基于 Java 的客户端来接收此消息,但无法正确解密该消息。我收到 javax.crypto.AEADBadTagException: 标签不匹配
错误。
该消息的结构如下:
header info (21 bytes)
nonce (12 bytes)
tag data (16 bytes)
encrypted payload (n bytes)
标头和随机数字节作为附加验证数据输入。
要解密的Java代码:
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init( Cipher.DECRYPT_MODE,
aesKey,
new GCMParameterSpec( 96, packet.getNonce() ));
cipher.updateAAD( packet.getHeaderAndNonce() );
return cipher.doFinal( packet.getEncryptedData() );
我在https://stackoverflow.com/a/26370130/212589中看到了Java中的内容加密时在密文末尾添加标签数据。我尝试更改 packet.getEncryptedData()
以返回以下内容:
- 标记数据(16 字节)+ 加密有效负载(n 字节)
- 加密有效负载(n 字节)+ 标记数据(16 字节)
,但这两种情况因相同的错误标签异常而失败。
我做错了什么?
作为参考,这里是进行加密的 C++ 代码:
const unsigned int NONCE_LEN = 12;
const unsigned int TAG_DATA_LEN = 16;
const unsigned int DATA_PACKET_HEADER_LEN = 49;
const unsigned int DATA_NONCE_OFFSET = 21;
const unsigned int DATA_TAG_DATA_OFFSET = 33;
std::array<byte, NONCE_LEN> randomNonce = getRandomNonce();
std::copy(randomNonce.begin(), randomNonce.end(), _data.begin() + DATA_NONCE_OFFSET);
EVP_EncryptInit_ex(cipherContext, EVP_aes_256_gcm(), nullptr, encryptionKey.data(), randomNonce.data());
int outlen;
EVP_EncryptUpdate(cipherContext, nullptr, &outlen, _data.data(), DATA_PACKET_HEADER_LEN - TAG_DATA_LEN);
EVP_EncryptUpdate(cipherContext, _data.data() + DATA_PACKET_HEADER_LEN, &outlen,
_payloadPlaintext.data(), _payloadPlaintext.size() );
EVP_EncryptFinal_ex(cipherContext, nullptr, &outlen);
EVP_CIPHER_CTX_ctrl(cipherContext, EVP_CTRL_GCM_GET_TAG, TAG_DATA_LEN, &_data[DATA_TAG_DATA_OFFSET]);
I have some existing C++ code that uses openssl to send an encrypted message.
I'm writing a new Java based client to receive this message and cannot properly decrypt the message. I'm getting javax.crypto.AEADBadTagException: Tag mismatch
errors.
The message is structured like this:
header info (21 bytes)
nonce (12 bytes)
tag data (16 bytes)
encrypted payload (n bytes)
The header and nonce bytes are input as Additional Authenticated Data.
The Java code to decrypt:
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init( Cipher.DECRYPT_MODE,
aesKey,
new GCMParameterSpec( 96, packet.getNonce() ));
cipher.updateAAD( packet.getHeaderAndNonce() );
return cipher.doFinal( packet.getEncryptedData() );
I see mention in https://stackoverflow.com/a/26370130/212589 that in Java the tag data is added at the end of the cipher text when encrypting. I have tried changing packet.getEncryptedData()
to return the following:
- tag data (16 bytes) + encrypted payload (n bytes)
- encrypted payload (n bytes) + tag data (16 bytes)
but both cases fail with the same bad tag exception.
What am I doing wrong?
For reference, here is the C++ code that is doing the encryption:
const unsigned int NONCE_LEN = 12;
const unsigned int TAG_DATA_LEN = 16;
const unsigned int DATA_PACKET_HEADER_LEN = 49;
const unsigned int DATA_NONCE_OFFSET = 21;
const unsigned int DATA_TAG_DATA_OFFSET = 33;
std::array<byte, NONCE_LEN> randomNonce = getRandomNonce();
std::copy(randomNonce.begin(), randomNonce.end(), _data.begin() + DATA_NONCE_OFFSET);
EVP_EncryptInit_ex(cipherContext, EVP_aes_256_gcm(), nullptr, encryptionKey.data(), randomNonce.data());
int outlen;
EVP_EncryptUpdate(cipherContext, nullptr, &outlen, _data.data(), DATA_PACKET_HEADER_LEN - TAG_DATA_LEN);
EVP_EncryptUpdate(cipherContext, _data.data() + DATA_PACKET_HEADER_LEN, &outlen,
_payloadPlaintext.data(), _payloadPlaintext.size() );
EVP_EncryptFinal_ex(cipherContext, nullptr, &outlen);
EVP_CIPHER_CTX_ctrl(cipherContext, EVP_CTRL_GCM_GET_TAG, TAG_DATA_LEN, &_data[DATA_TAG_DATA_OFFSET]);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我的解决方案有两个问题(请参阅@dave_thompson_085 的评论)
GCMParameterSpec
的标记长度参数是错误的。它应该是 128There were two issues with my solution (see @dave_thompson_085's comment)
GCMParameterSpec
was wrong. It should be 128