AES 的初始化向量(IV)或 Nonce 是公开元数据,不是第二把秘密密钥。它们的作用是保证重复执行加密时仍然安全。长度正确并不代表使用正确:不同模式对唯一性或不可预测性有不同要求,而重用 IV/Nonce 是现实系统中破坏性最强的加密错误之一。
IV、Nonce 与计数器的区别
这些术语有交集,但安全要求不同:
- IV 用于初始化 CBC 等模式。CBC 要求随机、不可预测的 16 字节 IV;
- Nonce 即“只使用一次的数”。GCM 通常要求唯一的 12 字节 Nonce;
- 计数器是按固定规则递增且不重复的结构化 Nonce,常用于 CTR 类模式。
这些值通常与密文一起保存。隐藏 IV 不能修复错误设计,而公开正确生成的 IV 也不会泄露密钥。
重用会破坏什么
| 模式 | 要求 | 重用后果 |
|---|---|---|
| CBC | 新的、不可预测的 16 字节 IV | 相同首分组产生相同首密文;可预测 IV 可被选择明文攻击利用 |
| CTR | 同一密钥下计数器流唯一 | 形成“两次一密”,异或密文会暴露明文异或值 |
| GCM | 同一密钥下 Nonce 唯一 | CTR 机密性失效,认证能力也可能被破坏 |
| OFB | 同一密钥下 IV 唯一 | 密钥流重复,暴露明文关系 |
CTR 与 GCM:密钥流重复
CTR 加密计数器分组,再与明文进行 XOR。如果相同密钥和初始计数器被重用:
C1 = P1 XOR S C2 = P2 XOR S C1 XOR C2 = P1 XOR P2
秘密密钥流 S 被抵消。只要某段明文具有固定结构或可被猜测,另一段明文就可能被恢复。GCM 内部使用 CTR,因此继承此问题;Nonce 重用还会在 GCM 认证计算中产生代数关系,风险不仅是明文泄露。
CBC:首分组关系泄露
CBC 在加密前将第一个明文分组与 IV 进行 XOR。同一密钥下重用 IV,会泄露两条消息的首个明文分组是否相同。可预测 IV 还可能让能控制明文的攻击者测试分组关系。
CBC 的 IV 重用不等同于 GCM 的 Nonce 重用,但同样违反模式的安全前提,必须作为缺陷处理。
安全生成方案
CBC 随机 IV
每次加密生成 16 个随机字节:
IV = CSPRNG(16 字节) 密文 = IV || AES-CBC(密钥, IV, 填充后明文)
使用操作系统或密码库提供的安全随机源。不要使用 Math.random()、时间戳、UUID 文本、明文哈希或固定配置值。
GCM 随机 Nonce
多数应用可使用密码学安全随机源生成 12 字节 Nonce。随着同一密钥下消息数量增长,碰撞概率会上升,因此应设定每把密钥的消息上限,并在风险达到不可接受水平前轮换密钥。
在分布式系统中,仅使用随机数并不等于完成设计。多个进程、虚拟机快照恢复或随机状态异常都可能造成重复。
GCM 结构化 Nonce
高吞吐系统可以组合唯一实例前缀与单调递增计数器:
Nonce = 32位实例ID || 64位消息计数器
实例 ID 不能冲突,密钥有效期间计数器不能归零。系统应在确认加密成功前持久化计数器,或给不同工作节点分配互不重叠的计数区间。
存储与密文封装
密文封装应明确每个字段:
版本 || 密钥ID || Nonce || 密文 || 认证标签
Nonce 应与加密记录一起保存。若版本、密钥 ID、租户或业务上下文不允许被修改,可以将其作为 GCM 附加认证数据(AAD)。
数据库可以对 (key_id, nonce) 建立唯一约束作为纵深防御。它不能替代正确分配机制,但能把灾难性的密码学故障转换为可观察的写入错误。
常见生产故障
配置中使用固定 IV
固定 IV 让测试结果可重复,却会破坏生产安全。测试代码可以注入确定性生成器,生产环境必须使用真实安全生成器。
服务重启后计数器归零
内存计数器在服务重启后从零开始。如果密钥没有更换,旧 Nonce 会再次出现。应持久化计数器、重启时轮换密钥,或分配持久化计数区间。
多个写入节点共享密钥
两台服务器可能生成相同计数值。应使用实例前缀划分 Nonce 空间或集中分配,并保证密钥关联数据存在期间实例 ID 不被重用。
加密请求重试
重试可能用同一个 Nonce 加密不同明文。幂等请求应直接返回之前完整的密文结果;重新执行加密时必须分配新 Nonce。
Nonce 被截断或转换
把 Nonce 转成整数、删除前导零或截断 UUID 会改变长度与唯一性。应定义固定二进制表示,并测试编码往返一致性。
检测与响应
如果系统不记录 Nonce 与密钥 ID,事后很难从密文本身发现重复。应记录非敏感封装元数据、监控唯一约束,并在故障切换演练中审计计数器。
确认 GCM Nonce 重用后:
- 停止使用受影响密钥继续加密;
- 生成新密钥并修复 Nonce 分配;
- 找出共享相同密钥与 Nonce 的全部记录;
- 将这些记录的机密性和真实性视为已受损;
- 只对可信明文使用新密钥重新加密。
仅为未来消息生成新 Nonce,不能修复已经受影响的记录。
实现检查清单
- 先确定模式,再确定 IV 规则;
- CBC 使用 16 字节安全随机 IV;
- GCM 使用唯一 12 字节 Nonce,除非库明确要求其他格式;
- 唯一性范围始终与具体密钥绑定;
- Nonce 和密钥 ID 与密文一起存储;
- 定义密钥轮换与每密钥消息上限;
- 测试重启、重试、并发、备份恢复和容灾切换。
模式选择可参考 AES-GCM 与 AES-CBC 对比。也可以使用 AES 加密工具配合非敏感测试向量观察 IV 行为。