AES-GCM 可以保护消息的机密性并检测未经授权的修改。但它本身并不能告诉接收者,一条在其他方面有效的消息是否已被处理。
有三个要求容易混淆:加密时密钥与 nonce 的组合唯一、对消息及其上下文进行认证,以及协议层面的重放处理。HKDF 可以帮助派生密钥,但不会自动满足全部三个要求。
Nonce 重用与重放是不同事件
| 事件 | 发生的情况 | 所需保护 |
|---|---|---|
| 加密时重用 nonce | 用同一个 GCM 密钥和 nonce 加密不同明文 | 可靠的密钥/nonce 分配策略 |
| 篡改 | 密文或经过认证的上下文被更改 | 认证解密,并在验证失败时拒绝 |
| 重放 | 再次投递一条之前有效的加密消息 | 识别重复消息或过时消息的状态与应用规则 |
| 乱序 | 有效消息以不同顺序到达 | 协议定义的顺序规则和有界的乱序处理 |
被重放的密文仍可能具有有效的认证标签,因为没有任何内容被更改。因此,声称每条重复消息都会自动无法通过 AES-GCM 认证,是不正确的。RFC 5116 明确区分 AEAD 接口与防重放服务。
为什么密钥与 nonce 的组合不能重复
GCM 的 nonce 不必保密,但在给定密钥下必须满足该方案的唯一性要求。96 位,即 12 字节的 nonce 很常见;选择这个长度并不能保证生成方式正确。
用相同密钥和 nonce 加密不同明文,会重用加密密钥流,从而暴露明文之间的关系。它还可能破坏真实性并使伪造成为可能。影响很严重,但不应描述成会自动泄露账户的每个旧密钥或每条消息。受影响范围取决于被重用的密钥和协议。
NIST SP 800-38D 定义了 GCM 及其要求。实现必须遵守适用的调用次数限制和 nonce 生成规则,而不是简单套用“在这么多条消息之前都是安全的”经验法则。
HKDF 的作用
RFC 5869 中规定的 HKDF 通过提取与扩展阶段,从输入的秘密材料派生密钥材料。协议可以使用上下文标签和不同输入,为不同用途分离密钥。
HKDF 是确定性的。如果崩溃或状态回滚后的客户端重复使用同一状态和输入,就可能再次派生出相同输出。因此,在设计中加入 HKDF 并不会让 nonce 重用变得不可能。
逐消息密钥可以减少任何一个密钥所保护的内容量,但安全推进状态、密钥分离和删除仍然重要。在确实不同的密钥下使用同一个 nonce 值,与重复密钥/nonce 组合不是同一种故障;协议必须确保这些密钥确实不同。
重放防护属于协议的职责
接收者可以跟踪消息标识符、序列位置、会话纪元或已经使用的棘轮密钥。相关字段必须经过认证,以免攻击者把旧消息重新标记为新消息。
随后,应用必须决定重复消息意味着什么。显示重复的聊天气泡会带来不便;将同一操作执行两次则可能更严重。网络重试很正常,因此除了密码学检查,通常还需要幂等处理。
除非协议规定如此,否则不要要求每条有效消息都严格按顺序到达。移动客户端经常重新连接、重试并接收延迟的消息。安全处理需要区分合法的迟到消息与已被处理或上下文错误的消息。
声称具备保护能力之前应测试什么
- 分配 nonce 后、记录发送之前重启:分配是否可能重复?
- 恢复较旧的状态快照:密钥、计数器或重放记录是否可能回滚?
- 从两个工作线程或设备并发发送:各自的密钥/nonce 域是否分离?
- 两次投递同一条有效消息:应用操作是否只执行一次?
- 更改会话标识符或头部:上下文是否通过密码学方式绑定?
- 乱序投递有效消息:能否处理受支持的延迟,而不接受过时状态?
认证解密 API 应当仅在验证成功时向应用返回明文。这是接口要求,并不是在声称任何实现都绝不会在内部计算临时明文缓冲区。
准确理解 Livara 的声明
Livara 的安全文档提到了 AES-256-GCM、逐消息链和 LVR1/LGS1 上下文。这些原语本身并不能证明崩溃恢复、nonce 分配或重放拒绝已正确实现。此类声明需要带版本的协议细节和测试证据。
健全的设计明确分配每项职责:密钥派生生成预期密钥,AEAD 认证内容和上下文,有状态的协议逻辑判断一条有效消息现在是否可以接受。



