4

I need to use AEAD to share information between two users, part of which must be encrypted and part of which should be kept in cleartext.

Is there an API to check the ciphertext tag and access the associated data once a message has been encrypted with AES/GCM ?

In more detail:

I'm using Java 7 with bouncycastle as a provider and I have managed to encrypt and decrypt my data successfully, using the corresponding 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);
}

However, it is my understanding that AES/GCM ciphertexts should already contain the parameters that could affect decryption (nonce and associatedData). Therefore, I would like to be able to retrieve them from the ciphertext, rather than having to store them alongside the ciphertext and pass them along to the decryption function. Furthermore, I'd like to be able to run integrity checks (computing the tag) and run some checks on the associated data without having to completely decrypt the message.

Is there an API that would allow this and that I might have missed ?

So far, I've checked:

4

2 回答 2

1

由于 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)

}

于 2017-12-01T11:34:40.600 回答
0

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

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

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

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

于 2014-05-28T19:10:07.537 回答