繁体   English   中英

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:无法为多重加密异常重用相同的密钥和 IV。

这是为了您的保护,希望库至少在同一个 Cipher 对象下使用时保持这种行为。

AES-GCM 内部在 CTR 模式下使用 AES 进行加密,对于 CTR 模式,(key,IV) 对的重用是由拖拽造成机密性的灾难性失败。

AES-GCM 使用 12 字节的 IV/nonce,其余的用于计数器。 前两个计数器值是保留的,因此您最多可以加密 2^32-2 个块,这将产生 2^39-256 位,并在单个(IV,密钥)对下产生大约 68-GB。

12 字节随机数是NIST 800-38d 的标准。 如果您提供的 nonce 不等于 12 字节,则它将使用GHASH进行处理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))

如果您按照 NIST 的建议使用基于计数器的 IV 生成,则不建议这样做,因为它会使它变得随机。 此外,由于 GHASH 调用,它会使您的加密速度变慢。

当我使用默认的 AES/GCM 算法初始化 Cipher 对象时,它有一个随机的 12 个字节的 IV,但前 4 个字节没有增加

这是预期的。 对应物再次设置为零。 由于您的文件比计数器支持的大,您想继续留在原处吗? 分割文件并制作链

  • 此外,请参阅正确使用 AES-GCM 的规则是什么?
  • 每当标签不正确时,根本不要使用明文。
  • 有一种 AES-GCM-SIV 模式可以消除 (IV,key) 对滥用。 它只会泄漏在相同的IV和密钥下再次发送相同的消息。
  • TLS 实际上每条记录使用一个新的 (key,IV) 对,最多有 2^14 字节,这可以防止内存填充攻击。 考虑到您在解密 68-GB 内存上花费了您的内存,那么您就会发现该标签是不正确的。 不错的服务器 DOS 攻击点。
  • 在可用的情况下,使用 ChaCha20-Poly1305 比 AES-GCM 容易得多。 不过,它仍然存在 (IV,key) 重用问题。
  • 有一个 XChaCha20 使用 192 位随机数和 64 位计数器。 这可以安全地处理非常大的数据大小和随机数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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