- • 整个 Session 唯一存在的"线索",跨越所有翻转
- • 每次 DH 翻转都喂入 KDF, 出新 RK + 新 ChainKey
- • send/recv 两个方向的 flip 都会推进它
- • 如果 Session 被 pickle 持久化, 必须保存 RK
- • 仅在"我已收到对方新 key"后才会更新
- • 触发更新的是"我的下一次 send", 不是 recv 本身
- • 同一个 SK 可发任意条消息(chain_index 递增)
- • 旧 SK 立即丢弃,节省存储
- • 镜像对方的 SendChain(Alice 的 RecvChain = Bob 的 SendChain)
- • 收到 ratchet_key 变化的 msg 时立即 reset
- • 同 ratchet_key 的多条消息推进同一条 RecvChain
- • 旧 RecvChain 可保留少量 skipped MK 处理乱序(详见 #06)
💡 一句话理解:
Double Ratchet 的"双" =
外层一根 DH 主链(RootKey, 跨轮持续翻新, 提供后向安全)
+ 内层两根对称子链(SendChain/RecvChain, 各自按对方密钥变化重置, 链内每步派生消息密钥提供前向安全)。
子链的 reset 才是"双棘轮"的关键 — 它把"前向安全"和"后向安全"焊在一起。
📚 基础知识速查 · Reference
不熟悉以下底层概念? 这里是 30 秒回顾。
设计模式有限状态机 (FSM)
由"状态 + 事件 + 转移函数"组成的模型。Signal 的"棘轮翻转"可建模为 FSM, 转移由 send / recv 事件驱动。
state' = transition(state, event)
工程不可变状态 (Immutable State)
每次"翻转"产生新状态对象, 旧状态直接丢弃 (zeroize)。便于推理、测试与并发安全。
let new_state = ratchet.flip();
old_state.zeroize();
协议Double Ratchet 三层状态
RootKey (跨轮持久) + SendChain (单轮发送) + RecvChain (单轮接收)。这是 Signal 最核心的状态空间设计。
{ rk, send_chain, recv_chain, dh_pair }
概念持久化 (Pickle)
把内存里的 Session 状态序列化到磁盘, 重启后恢复。Olm/vodozemac 的 pickle 必须保护 RootKey 等敏感字段。
session.pickle(passphrase) → bytes