java - Java AES/GCM/NoPadding 加密在 doFinal 之后不会增加 IV 的计数器
问题描述
当我使用默认的 AES/GCM 算法初始化 Cipher 对象时,它有一个随机的 12 字节 IV,但在调用 doFinal 并抛出java.lang.IllegalStateException: Cannot re-use same key 和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
大小将为 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 位计数器。这可以安全地处理非常大的数据大小和随机随机数。
推荐阅读
- python - 如何在 Python 2 到 3 升级中修改“{:<25}”格式
- python - 使用隔离森林对分类数据进行异常检测
- spring - Spring Boot 多重认证
- java - 为什么我无法从片段参数中获取字符串?
- java - 求解常数空间中的排序算法
- reactjs - nextjs- typescript- 属性 'className' 不存在于类型'IntrinsicAttributes & IntrinsicClassAttributes
- facebook - 共享链接的特色图片从 Facebook 中消失
- angular - 如何在angular6中为卡片类型编写开关条件
- postgresql - 如何加密 Postgres 9.6 数据库
- c# - 从 WPF 中的外部类绑定