使用Java中的身份验证标记实现AES GCM

use*_*812 6 java encryption android ios aes-gcm

我在我的android项目中使用AES GCM身份验证,它工作正常.但与openssl API生成标记相比,在验证标记时遇到一些问题.请在下面找到java代码:

SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
byte[] iv = generateRandomIV();
IvParameterSpec ivspec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
int outputLength = cipher.getOutputSize(data.length); // Prepare output buffer
byte[] output = new byte[outputLength];
int outputOffset = cipher.update(data, 0, data.length, output, 0);// Produce cipher text
outputOffset += cipher.doFinal(output, outputOffset);
Run Code Online (Sandbox Code Playgroud)

我在iOS中使用openssl,并使用下面的代码生成身份验证标记

NSMutableData* tag = [NSMutableData dataWithLength:tagSize];
EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, [tag length], [tag mutableBytes])
Run Code Online (Sandbox Code Playgroud)

在java或bouncy castle中,无法获得openssl返回的确切身份验证标记,并且可以帮助我解决此问题.谢谢

Maa*_*wes 7

在Java中,不幸的是,标签是在密文末尾添加的。您可以使用来配置大小(以8的倍数为单位)GCMParameterSpec。因此,您可以根据需要使用它Arrays.copyOfRange(ciphertext, ciphertext.length - (tagSize / Byte.SIZE), ciphertext.length)

不幸的是,因为标签不具有在结束时说,它使混乱起来GCM的在线本质解密 -需要内部缓冲,而不是能够直接返回明文。另一方面,在解密过程中会自动验证标签。

  • 但!如果我错了请纠正我 - 我一定是这样 - 不是说 MAC 是所有输入字节的哈希值吗?那么实现肯定必须“记住”所有字节才能计算 MAC?这可以解释为什么 MAC(在本例中是“身份验证标签”)被放置在密文的末尾,并解释了内部缓冲?如果您愿意的话,请详细说明这个问题,因为它对我以及其他许多人来说非常重要。谢谢猫头鹰斯特德!你太棒了。 (3认同)
  • 完毕。请参阅[http://stackoverflow.com/q/26920906/1268003](http://stackoverflow.com/q/26920906/1268003)。 (2认同)