简体   繁体   中英

How to decrypt AES-GCM encoded message using AAD in Java

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:

  1. tag data (16 bytes) + encrypted payload (n bytes)
  2. 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]);

There were two issues with my solution (see @dave_thompson_085's comment)

  1. The tag length parameter passed to GCMParameterSpec was wrong. It should be 128
  2. The Java decrypt assumes the tag data is at the end of the ciphertext, so in my case I had to move the tag data bytes from the beginning.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM