摘要

  • TLS 1.3 的 KeyUpdate 是单向操作:发送方推进写秘密,对端同步推进对应的读秘密;反向流量只有经过另一次更新才会换代。
  • 安全删除旧代秘密,可以让后来泄露的新秘密难以追溯早期流量;但掌握当前秘密的人能够继续算出后续代际,所以派生式轮换不能修复已经失陷的连接。

一条连接里有两条代际线

“更换连接密钥”这句话很容易制造错误图景,仿佛双方共同扔掉一把钥匙,再同时拿起另一把。TLS 1.3 的应用流量不是这样组织的。客户端到服务器、服务器到客户端各有自己的流量秘密;它们沿着两条独立链前进。

这种安排首先回应的是用量问题。AEAD 算法对同一密钥可安全处理的数据量存在保密性和完整性界限。握手成功并不会把这个额度变成无限。RFC 8446 要求实现避免逼近相应上限,并建议在达到界限之前更新密钥。RFC 9325 也提醒长连接应用认真设计会话密钥更新策略。

旧版 TLS 可以在现有连接里重新协商。那是一项覆盖面很大的操作,可能把参数、密钥和身份问题重新带回正在工作的会话。TLS 1.3 删除了重新协商,把握手后的任务拆成权限更小的机制。KeyUpdate 不换协议版本、不重选密码套件、不替换证书,也不重置应用会话;它只推进应用流量保护所用的秘密。

更新通知由旧密钥送达

代际分界不是双方依靠时间猜出的瞬间。发送方先用旧写密钥加密 KeyUpdate 消息,随后发出的所有记录才使用新写密钥。接收方以当前读密钥验证这条消息,然后推进相应的接收秘密,准备处理后续记录。

这项次序让更新本身成为受保护记录序列的一部分。切换过早,就读不懂那条更新消息;切换过晚,就打不开第一条新代记录。实现必须按照流中的真实边界推进状态,不能把它当作独立控制面的布尔开关。

如果消息携带 update_not_requested,这次操作到此为止:一端的发送方向和另一端对应的接收方向进入新代,反向仍保持原状。如果携带 update_requested,对端需要另发一条 KeyUpdate,并用 update_not_requested 回应。反向换代是第二个受保护动作,不是第一条消息附带的同步效果。

两端可能各自发起请求,使消息在途中交叉。规范要求双方仍正确回应,但不允许在尚未收到前一次请求的响应时继续索要下一次更新。Finished 之前收到 KeyUpdate 也必须报错。对于过量更新,实现还应设置处理上限:允许对端推动密码学状态,并不等于允许它制造无限计算负担。

删除旧代保护过去,当前代暴露未来

完成过渡并确认旧秘密不再用于在途记录后,端点可以把它删除。若攻击者日后只拿到较新的流量秘密,单向派生关系不会自动交出更早的秘密。已经捕获的旧密文因此可能继续受到保护。这是密钥换代的重要收益。

但箭头朝向未来。知道当前流量秘密的人可以算出它的后继。再执行一次 KeyUpdate,只是沿着一条已知链继续前进;过程中没有加入独立新熵,也没有重新验证对端身份。

所以,两个看似都叫“轮换”的场景必须分开。记录数量或字节量接近 AEAD 使用界限时,应推进代际。若有证据表明当前秘密已经泄露,则应终止连接,通过新握手获得新的秘密来源。拿持续的 KeyUpdate 活动当作事件恢复,可能让攻击者跟着派生链一直留在连接里。

HTTP/2 接受换钥,不接受中途换身份

HTTP/2 的多路复用把权限边界照得很清楚。一条连接上可能同时存在许多请求。若握手后突然更换连接级认证身份,很难可靠判断每条流究竟属于哪个身份。RFC 9113 因此禁止 HTTP/2 使用 TLS 1.3 的握手后认证。

同一规范却允许 KeyUpdate,因为记录保护秘密的变化不会直接改变 HTTP 请求的身份或授权含义。已有流继续运行,只是底层某一方向进入新的密码学代际。它之所以适合多路复用,恰恰因为它没有继承重新协商的广泛权力。

QUIC 又画出另一道边界。RFC 9001 明确禁止在 QUIC 中发送 TLS KeyUpdate 消息。QUIC 数据包可能乱序,因此使用自己的 Key Phase 位与确认规则完成换钥。目标相似,但依赖有序 TLS 记录流的机制不能直接移植到数据报传输。

轮换的价值来自不越权

KeyUpdate 不证明对端依然可信,不重新授权用户,不清空应用状态,也不宣告安全事件已经结束。它管理的是同一连接里、按方向划分的流量秘密代际。

这项狭窄职责正是 TLS 1.3 的历史进步:把日常密码学维护从身份和应用语义中拆开。新密钥可以承担新的使用额度,却仍继承旧秘密的谱系。理解这两句话同时成立,才算真正理解了轮换。

来源与边界

本文依据 RFC 8446RFC 9001RFC 9113RFC 9325。这些规范不提供当前产品支持率、部署比例、库默认行为或适用于所有系统的统一更新周期。