Java AES/GCM/NoPadding 加密不会在 doFinal 之后增加 IV 的计数器
Java AES/GCM/NoPadding encryption does not increment the counter of the IV after doFinal
当我使用默认 AES/GCM 算法初始化 Cipher 对象时,它有一个随机的 12 字节 IV,但前 4 个字节在调用 doFinal 并抛出 java.lang.IllegalStateException: 不能重复使用相同的密钥和 IV 进行多次加密 异常。
SecretKey secretKey = ...
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] iv1 = encCipher.getIV();
byte[] ctext = encCipher.doFinal("a".getBytes());
cipher.update("b".getBytes());
byte[] iv2 = encCipher.getIV();
ctext = encCipher.doFinal();
java.lang.IllegalStateException: Cannot re-use same key and IV for multiple encryptions exception.
这是为了保护您,希望库至少在同一个 Cipher 对象下使用时保持此行为。
AES-GCM 在 CTR 模式内部使用 AES 进行加密,对于 CTR 模式,(key,IV) 对的重用是 crib-dragging 机密性的灾难性失败。
AES-GCM使用了12个字节IV/nonce,剩下的用于计数器。前两个计数器值是保留的,因此您最多可以加密 2^32-2 个块,这使得 2^39-256 位和在单个(IV,密钥)对下大约 68-GB。
12字节的随机数是NIST 800-38d. If you supply a nonce not equal to 12-byte, then it will be processed和GHASH
的标准,之后的大小将是12字节。
if len(IV) = 96 then
J_0 = IV || 0^{31}1
else
J_0=GHASH_H(IV||0^{s+64}||len(IV_64))
不建议使用counter-based IV generation as suggested by NIST,因为它会使它变得随机。此外,由于 GHASH 调用,它会使您的加密速度变慢。
When I initialize a Cipher object with the default AES/GCM algorithm, it has a reandom 12 bytes IV but the first 4 byte does not get incremented
这是预期的结果。对方再次设置为零。由于您的文件大于计数器支持的大小,您是否要从剩下的地方继续? .
- 此外,参见 What are the rules for using AES-GCM correctly?
- 只要标签不正确,就不要使用明文。
- 有一个 AES-GCM-SIV 模式可以消除 (IV,key) 对的误用。它只是泄漏了相同的消息在相同的 IV 和密钥下再次发送。
- TLS 实际上对每个记录使用一个新的 (key,IV) 对,它最多有 2^14 字节,这可以防止内存填充攻击。假设您将内存用于 68 GB 的解密,那么您会发现标签不正确。不错的服务器 DOS 攻击点。
- 使用 ChaCha20-Poly1305 比 AES-GCM 容易得多。不过,它仍然存在 (IV,key)-重用问题。
- 有一个使用 192 位随机数和 64 位计数器的 XChaCha20。这可以安全地处理非常大的数据大小和随机随机数。
当我使用默认 AES/GCM 算法初始化 Cipher 对象时,它有一个随机的 12 字节 IV,但前 4 个字节在调用 doFinal 并抛出 java.lang.IllegalStateException: 不能重复使用相同的密钥和 IV 进行多次加密 异常。
SecretKey secretKey = ...
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] iv1 = encCipher.getIV();
byte[] ctext = encCipher.doFinal("a".getBytes());
cipher.update("b".getBytes());
byte[] iv2 = encCipher.getIV();
ctext = encCipher.doFinal();
java.lang.IllegalStateException: Cannot re-use same key and IV for multiple encryptions exception.
这是为了保护您,希望库至少在同一个 Cipher 对象下使用时保持此行为。
AES-GCM 在 CTR 模式内部使用 AES 进行加密,对于 CTR 模式,(key,IV) 对的重用是 crib-dragging 机密性的灾难性失败。
AES-GCM使用了12个字节IV/nonce,剩下的用于计数器。前两个计数器值是保留的,因此您最多可以加密 2^32-2 个块,这使得 2^39-256 位和在单个(IV,密钥)对下大约 68-GB。
12字节的随机数是NIST 800-38d. If you supply a nonce not equal to 12-byte, then it will be processed和GHASH
的标准,之后的大小将是12字节。
if len(IV) = 96 then
J_0 = IV || 0^{31}1
else
J_0=GHASH_H(IV||0^{s+64}||len(IV_64))
不建议使用counter-based IV generation as suggested by NIST,因为它会使它变得随机。此外,由于 GHASH 调用,它会使您的加密速度变慢。
When I initialize a Cipher object with the default AES/GCM algorithm, it has a reandom 12 bytes IV but the first 4 byte does not get incremented
这是预期的结果。对方再次设置为零。由于您的文件大于计数器支持的大小,您是否要从剩下的地方继续?
- 此外,参见 What are the rules for using AES-GCM correctly?
- 只要标签不正确,就不要使用明文。
- 有一个 AES-GCM-SIV 模式可以消除 (IV,key) 对的误用。它只是泄漏了相同的消息在相同的 IV 和密钥下再次发送。
- TLS 实际上对每个记录使用一个新的 (key,IV) 对,它最多有 2^14 字节,这可以防止内存填充攻击。假设您将内存用于 68 GB 的解密,那么您会发现标签不正确。不错的服务器 DOS 攻击点。
- 使用 ChaCha20-Poly1305 比 AES-GCM 容易得多。不过,它仍然存在 (IV,key)-重用问题。
- 有一个使用 192 位随机数和 64 位计数器的 XChaCha20。这可以安全地处理非常大的数据大小和随机随机数。