每五百条消息换一次锁:BOLT 8 的传输密钥轮换 图 1
每五百条消息换一次锁:BOLT 8 的传输密钥轮换 · 图 1

一条长连接,两把快换的锁

闪电节点之间的每条 TCP 连接都建立在 BOLT 8 定义的加密传输之上:握手阶段用 Noise_XK 模式交换临时密钥,推导出发送与接收两把对称密钥(sk 与 rk),此后消息用 ChaCha20-Poly1305 加密认证。连接可以存活数周,消息可以往来百万条——但密钥不是。规范规定:每条密钥单独计数,一方用某把密钥加密或解密累计一千次(即每五百条消息,因为每条消息的收发各计一次单边用量)后,密钥必须更换;链值同步推进,旧值随轮换抛弃。

每五百条消息换一次锁:BOLT 8 的传输密钥轮换 图 2
每五百条消息换一次锁:BOLT 8 的传输密钥轮换 · 图 2

为什么每五百条

数字来自密码学的用量边界而非拍脑袋。ChaCha20-Poly1305 的每条消息配一个九十六位随机数(nonce),密钥与随机数组合一旦重用,认证加密的安全性彻底崩塌。轮换把“同一密钥下随机数被用掉多少”变成可精确核算的账:密钥链值即计数器,用到第一千个随机数就换钥,从根本上杜绝计数器回绕或重用。规范建议的实现方式是把链值当作随机数的来源——轮换后计数归零,新密钥配新序列,账本干净。

轮换的第二个动因是密钥泄露的爆炸半径。闪电连接是长期会话,若某把对称密钥在数月后被攻破,用它加密的全部历史消息都将暴露。按固定用量强制换锁、旧链值不可回推,意味着即便未来某天泄露当下的密钥,攻击者能解密的也只是这一小段窗口内的流量——规范把这层性质明确称为向后保密。

轮换怎么做而不打断连接

密钥交换(握手)只在连接建立时做一次;轮换是握手结束后的内部动作,双方各自维护自己的发送密钥与接收密钥,各转各的计数:用链值做一次 HKDF 派生出新密钥与新链值,计数清零,继续发下一条。对端不需要任何额外协商——它按同样的规则算出同一把新钥。因此轮换对上层消息(打开通道、HTLC、gossip 转发)完全透明,不存在“换锁窗口”。

值得注意的是方向不对称:每条连接两个方向的密钥独立,一端可能已经换到第七把锁而另一端的计数还没触发第一次轮换。实现若把两侧状态误共享,就会出现解密错序——这是规范测试向量专门覆盖的错误类型。

与比特币 BIP324 的区别

容易混淆的另一套机制:比特币节点的 P2P 加密(BIP324 的 v2 传输)同样基于 Noise 协议家族,但传输密钥的生命周期管理走的是各自规范的逻辑。闪电的这条规则绑定在消息计数上,服务于长会话下的最小暴露窗口;两者规范独立、实现独立,读论文与日志时不要互相套用参数。

一个直觉算术

每五百条消息一换,意味着高频通道的密钥寿命以分钟到小时计。对比噪声协议族对 ChaCha20-Poly1305 随机数用量的安全界,千次用量留有数量级的余量;对比一把锁用到连接关闭的旧思路,泄露窗口被切成了上千个片段。两个方向都留了裕度,这正是规范选择这个数字的方式:不是最优,而是两侧都远离边界。

快速问答

问:轮换会泄露“已经发了多少消息”吗? 答:从单侧密文不能直接读出计数。但把换钥节奏与流量节律结合,长期观测者可能对会话活跃度有弱推断,这属于流量分析层面的边界,不在传输加密承诺范围内。

问:为什么不用更频繁的轮换? 答:每次换钥要重做密钥派生并重置计数器,规范选择与算法安全边界对齐的保守值:千次用量远在任何可证明安全界之内,同时把泄露窗口切得足够小。

风险提示

本文描述公开传输规范,不构成组网或密码方案选型建议。实现请使用经过审计的密码库,细节以 BOLT 8 当前版本为准。