从 2016 年的 X3DH 到 2023 年的 PQXDH,再到 2025 年的 SPQR / Triple Ratchet—— Signal 协议是怎样在不破坏 forward secrecy 的前提下,把每一段密钥协商都"加上抗量子保险"的。
Signal 2016 年定型的 X3DH 在异步握手里做 4 次 DH,全部跑在 Curve25519 上。
安全性押在 椭圆曲线离散对数难题——Shor 算法跑在足够大的量子计算机上就能在多项式时间内打掉。
真正的威胁不是"等量子计算机来了再换",而是今天就发生的 harvest-now-decrypt-later:国家级对手现在录下所有密文,等 CRQC(密码相关规模量子计算机)问世—— 预计 10–20 年——一次性解密。Signal 主打的 forward secrecy 在这套威胁模型下失效: 虽然每条消息密钥都已删除,但首密钥能被反算出来,整段历史会话照样泄漏。
所以 PQ 升级不能等。Signal 在 2023-09-19 公告了 PQXDH
(Post-Quantum Extended Diffie-Hellman),把一个后量子 KEM 拼到 X3DH 旁边,hybrid 协商首密钥。
NIST 在 2016 年发起后量子密码标准化竞赛。2022 年 7 月,CRYSTALS-Kyber 入选为唯一的 KEM 标准化候选;
2024 年 8 月,正式发布 FIPS 203 · ML-KEM(Module-Lattice-based KEM),是 Kyber 的标准化版本。
ML-KEM 基于 Module Learning With Errors (MLWE) 困难假设,参数集:
ML-KEM-512 公钥 800 B · 密文 768 B · 类比 AES-128 ML-KEM-768 公钥 1184 B · 密文 1088 B · 类比 AES-192 ML-KEM-1024 公钥 1568 B · 密文 1568 B · 类比 AES-256
Signal 在 PQXDH 中明确推荐用 Kyber-1024(最高安全等级),现在等价于 ML-KEM-1024。
Spec 原文:"an application could choose ... pqkem as CRYSTALS-KYBER-1024"。
在看 PQXDH 算法之前必须先迁移一个心智:后量子原语主流不是"DH 的替换品",而是 KEM(Key Encapsulation Mechanism)。 二者的 API 形态根本不同——这一节看不懂的话,第 03 节的算法图会一直被误读成"加了第 5 个 DH"。
DH(a, B) = DH(b, A)(ct, ss)这个差异决定了 PQXDH 的整体形态。不是"用 ML-KEM 替换 X25519",而是 X25519 的 4 个 DH 保持不变,旁边并联一个 ML-KEM 的 Encap/Decap, 两套各算出一段 shared secret,再用 KDF 揉到一起。
同样的原因,会话内的 Double Ratchet 也不能"直接换 KEM"——下文第 04 节会展开。
看图。左侧是 Bob 的 prekey bundle——除 X3DH 原有字段外,多了两类 ML-KEM 公钥(PQSPK 长期、PQOPK 一次性),
以及它们各自由 IK_B 做的签名。中间是 Alice 的本地计算:4 个 DH 一切照旧(沿用 X3DH),
外加一次 Encap(PQPK_B) 吐出 (CT, SS)。右侧是 共同的 KDF 输入——
DH1‖DH2‖DH3‖DH4‖SS 一起喂给 HKDF 得到首密钥 SK。
Hybrid 的安全论证:KDF 是密码学伪随机函数,只要任意一个输入有足够熵且无法被反算,输出 SK 就安全。
所以——
PQXDH spec § 3.3 定义的 KDF 输入:
F = b'\xFF' × 32 // domain separation prefix KM = F ‖ DH1 ‖ DH2 ‖ DH3 [‖ DH4] ‖ SS SK = HKDF(salt = 0×64, ikm = KM, info = "MyProtocol")
关键约束(来自 spec 原文):"If pqkem does not incorporate PQPK_B
into the ciphertext, Alice must also append EncodeKEM(PQPK_B) to AD."
这是防 KEM key-substitution 攻击——若 KEM ciphertext 本身没把 pk 绑死,
需要靠 AD 在 AEAD 这层把 pk 绑定到会话身份上,否则攻击者可以替换 PQPK 重放。
PQXDH 只升级了初始握手。一旦会话建立,后续靠 Double Ratchet 持续派生消息密钥;
其中 DH Ratchet 那一支——每条消息附带的临时公钥——仍然是 X25519。
意味着:
Signal 在 2025-10-02 公告了 SPQR(Sparse Post-Quantum Ratchet),并把它与 Double Ratchet 组合成
Triple Ratchet。截至 2026-05,iOS 和 Android 主分支都已在 capability 层无条件声明 spqr = true:
AccountAttributes.swift:105 · public let spqr = trueAppCapabilities.kt · spqr = true(硬编码)
意味着两端客户端都已经 ship 了 SPQR 支持代码,并向服务器宣告自己具备这个能力。
实际生效仍需会话双方都已升级(不然就 fallback 到老 Double Ratchet)——但既然两个主流客户端都是无条件 true,
随着自动更新覆盖到大部分用户,大部分新会话现在应该都是 Triple Ratchet 了。
SPQR 的核心工程难点是带宽:ML-KEM ciphertext ~1568 B,远大于 X25519 的 32 B。 如果每条消息都附一个完整 KEM ciphertext,移动网络成本无法接受。 SPQR 用了两个手段缓解——
官方公告:"Signal Protocol and Post-Quantum Ratchets" · signal.org/blog/spqr · 2025-10-02。
技术亮点:
"Triple" 这个命名学界其实 2024 年就有论文用过(如 "The Triple Ratchet" by Alwen et al.),但 Signal 工程实现与论文方案在细节(erasure code 形式、状态机布局)上不完全相同。
DR 的 DH Ratchet 之所以优雅,靠的是 DH 的对称性:双方都"亮一次自己的临时公钥",对方就能算出共享。 KEM 没有这个性质:
所以 SPQR 选了"sparse + erasure-coded"这条折中路:保留 DH Ratchet 不变,把 KEM 作为并联的、稀疏触发的第三条链。
| 版本 | 时间 | 关键变化 | 仍然脆弱的部分 |
|---|---|---|---|
| Axolotl / DR | 2013 | DH Ratchet + Symmetric Ratchet 雏形 | 异步首握手不优雅 |
| X3DH + DR | 2016 | 引入 SPK + OPK 解决异步握手 | 全栈 X25519 → 量子来即崩 |
| PQXDH | 2023-09 | X3DH ⊕ Kyber-1024, hybrid 初始握手 | 会话内 DH Ratchet 仍 X25519 |
| SPQR / Triple Ratchet | 2025-10 | DR + sparse ML-KEM hybrid, 形式化验证 | iOS + Android 双端 capability 已硬编码 spqr = true · 旧设备未升前会话仍走 DR |
spqr = true capability 声明 (iOS 已 ship)spqr = true (Android 已 ship)