Signal X3DH 密钥协商协议原理:异步端到端加密的数学基础
概述
X3DH(Extended Triple Diffie-Hellman,扩展三重 Diffie-Hellman) 是由 Moxie Marlinspike 和 Trevor Perrin 在 2016 年设计的密钥协商协议,是 Signal 协议套件的核心组件。它为异步通信场景下的端到端加密建立了安全的共享密钥——即使接收方不在在线,发送方也能利用接收方预先生成的公开密钥材料(prekey)建立加密会话。
X3DH 的核心设计目标:
- 前向保密(Forward Secrecy):长期密钥泄露不会暴露过去的会话密钥
- 后向保密(Backward Secrecy):临时密钥泄露不会暴露未来的会话密钥
- 密码学可否认性(Cryptographic Deniability):通信双方无法向第三方证明对方发送了某条消息
- 异步性(Asynchrony):接收方无需在线即可建立安全会话
协议角色与密钥体系
1.1 三方参与者
X3DH 涉及三个角色:
- Alice(发起方):主动发起通信请求的用户
- Bob(响应方):接收通信请求的用户(可能离线)
- 服务器:存储 Bob 的预密钥信息,存储加密消息(服务器无法解密)
1.2 五级密钥架构
X3DH 使用五种椭圆曲线公钥:
| 密钥名称 | 符号 | 生命周期 | 用途 |
|---|---|---|---|
| 身份密钥(Identity Key) | IKA / IKB | 长期(数年) | 代表用户身份,相互认证 |
| 签名预密钥(Signed Prekey) | SPKB | 中期(数周) | 定期轮换,增强前向保密 |
| 一次性预密钥(One-time Prekey) | OPKB | 单次 | 每次使用后删除,最大化前向保密 |
| 临时密钥(Ephemeral Key) | EKA | 单次 | Alice 每会话生成 |
- IKB:用户注册时生成,长期保存
- SPKB:服务器预密钥不足时由客户端生成(通常每周轮换)
- OPKB:客户端预生成一批(通常 100 个)上传到服务器
- EKA:Alice 每次发起会话时生成
1.3 密钥参数
X3DH 支持两种椭圆曲线参数:
- X25519:256 位 Curve25519,产生 256 位安全强度
- X448:448 位 Curve448,产生 224 位安全强度(后量子过渡选择)
- 哈希函数:SHA-256 或 SHA-512
- info 字符串:应用标识符(如 \"SignalProtocol\")
协议流程
2.1 阶段一:Bob 发布密钥
Bob 将以下服务器信息通过服务器公布:
Bob → Server:
IKB (Bob 的身份公钥)
SPKB (Bob 的签名预密钥公钥)
Sig(IKB, Encode(SPKB)) (用 IKB 对 SPKB 的签名)
OPKB1, OPKB2, ... OPKBn (Bob 的一次性预密钥集合)签名目的:防止服务器替换 SPKB——Alice 可以通过验证签名确认 SPKB 确实来自 IKB 的持有者。
2.2 阶段二:Alice 发送初始消息
Alice 从服务器获取 Bob 的预密钥包(prekey bundle):
Server → Alice:
IKB
SPKB
Sig(IKB, Encode(SPKB))
(可选) OPKB验证步骤:
- Alice 验证
Sig(IKB, Encode(SPKB)),确保 SPKB 未被篡改 - 验证失败则中止协议
Alice 生成临时密钥对 (EKA),然后根据是否包含 OPKB 计算共享密钥:
无 OPKB 时(三次 DH):
DH1 = DH(IKA, SPKB) ← Alice 长期密钥 × Bob 中期密钥
DH2 = DH(EKA, IKB) ← Alice 临时密钥 × Bob 长期密钥
DH3 = DH(EKA, SPKB) ← Alice 临时密钥 × Bob 中期密钥
SK = KDF(DH1 ∥ DH2 ∥ DH3)有 OPKB 时(四次 DH):
DH1 = DH(IKA, SPKB) ← Alice 长期密钥 × Bob 中期密钥
DH2 = DH(EKA, IKB) ← Alice 临时密钥 × Bob 长期密钥
DH3 = DH(EKA, SPKB) ← Alice 临时密钥 × Bob 中期密钥
DH4 = DH(EKA, OPKB) ← Alice 临时密钥 × Bob 一次性密钥
SK = KDF(DH1 ∥ DH2 ∥ DH3 ∥ DH4)2.3 DH 交换的安全语义
四次 DH 交换各自提供不同的安全保证:
| DH 计算 | 安全属性 |
|---|---|
| DH1 = DH(IKA, SPKB) | 认证绑定:双方的身份密钥被绑定到会话中 |
| DH2 = DH(EKA, IKB) | Alice 认证:证明 Alice 持有 IKA 对应的私钥 |
| DH3 = DH(EKA, SPKB) | 前向保密:临时密钥保证即使长期密钥泄露也无法追溯 |
| DH4 = DH(EKA, OPKB) | 更强前向保密:一次性密钥确保本会话绝对唯一 |
2.4 KDF 密钥派生
共享密钥通过 HKDF 派生:
KDF(KM) = HKDF(
input_key_material = F ∥ KM,
salt = 空字符串,
info = 应用标识符
)其中 F 是 32 字节(X25519)或 57 字节(X448)的 0xFF 填充,用于域分离(Domain Separation)。
输出:32 字节的会话密钥 SK。
2.5 Alice 发送的消息结构
Alice 发送给 Bob 的初始消息包含:
Alice → Bob:
IKA (Alice 的身份公钥)
EKA (Alice 的临时公钥)
prekey_id (标识使用了哪些 Bob 的预密钥)
initial_ciphertext (使用 SK + AEAD 加密的首条消息)关联数据(Associated Data):
AD = Encode(IKA) ∥ Encode(IKB)AD 将双方身份绑定到 AEAD 认证中,防止身份错绑定攻击(Identity Misbinding Attack)。
2.6 阶段三:Bob 处理初始消息
Bob 收到 Alice 的初始消息后:
- 加载对应私钥(IKB 私钥、SPKB 私钥、OPKB 私钥)
- 执行相同的 DH 和 KDF 计算得到 SK
- 构造相同的 AD
- 尝试解密
initial_ciphertext - 解密失败则中止协议,删除 SK
- 解密成功则删除 OPKB 的私钥(一次性密钥使用一次后即弃)
安全分析
3.1 前向保密(Forward Secrecy)
假设场景:攻击者在时间 T 窃取了 Bob 的所有密钥(IKB + SPKB + OPKB 集合),但在 T 之前建立的会话中有 Alice 想要保密的消息。
保护机制:
- 之前的会话密钥 SK 依赖 EKA,而 EKA 是 Alice 每次会话临时生成并在发送后立即删除的
- 攻击者无法从 DH3 = DH(EKA, SPKB) 反推 EKA(离散对数困难性)
- 因此无法计算之前会话的 SK
3.2 后向保密(Post-Compromise Security)
假设场景:攻击者在时间 T 窃取了 Alice 的身份私钥,希望解密之后建立的会话。
保护机制:
- 未来会话依赖 EKA(每次新生成)和 OPKB(每次使用后删除)
- DH3 和 DH4 引入了新的熵源
- 经过若干次会话后,DH 累积的熵将攻击者\"淘汰\"在外
- 此属性在双棘轮(Double Ratchet) 算法中进一步强化
3.3 密码学可否认性(Cryptographic Deniability)
X3DH 提供 在线可否认性:
- Bob 无法向第三方 Charlie 证明 Alice 发送了某条消息
- 因为 Charlie 可以声称 \"这些消息是我自己用我的私钥和 Alice 的私钥伪造的\"
- 但这种可否认性不适用于实时通信场景(Alice 正在与 Bob 交互时无法否认)
3.4 重放攻击(Replay Attack)
问题:如果 Alice 的初始消息不使用 OPKB,攻击者可以在服务器上重放该消息,Bob 会接受并产生相同的 SK。
缓解策略:
- 在双棘轮协议中,Bob 在首次回复时会进行新的 DH 棘轮步骤,产生随机化的新密钥
- 服务器可以维护一个已观察消息的短名单进行重放检测
3.5 密钥妥协模拟(Key-Compromise Impersonation, KCI)
攻击场景:攻击者获取了 Bob 的所有密钥,希望冒充 Alice 与 Bob 通信。
保护:DH1 = DH(IKA, SPKB) 要求攻击者知道 Alice 的 IKA 私钥才能正确计算 DH1。因此,仅获取 Bob 的密钥无法冒充 Alice。
3.6 服务器信任模型
X3DH 的设计假设服务器是 semi-honest(半诚实) 的:
- 服务器可能拒绝服务(不转发消息)
- 服务器可能耗尽 Bob 的 OPKB,降低前向保密保证(此时仅依赖 SPKB 的轮换频率)
- 但服务器无法读取消息内容(无 SK)
PQXDH:后量子扩展
4.1 威胁模型
量子计算机能够破解 X25519 和 X448 的离散对数问题,从而威胁 X3DH 的长期安全性。
4.2 PQXDH 设计
PQXDH(Post-Quantum X3DH) 在 X3DH 基础上增加了后量子 KEM(Key Encapsulation Mechanism,密钥封装机制):
传统 X3DH:
SK = KDF(DH1 ∥ DH2 ∥ DH3 ∥ DH4)
PQXDH:
SK = KDF(DH1 ∥ DH2 ∥ DH3 ∥ DH4 ∥ PQ_shared_secret)其中 PQ_shared_secret 是 ML-KEM(FIPS 203,即 CRYSTALS-Kyber)封装产生的共享密钥。
4.3 安全保证
PQXDH 提供 混合安全:攻击者必须同时破解:
- 离散对数假设(X25519)和
- 格密码假设(ML-KEM)
与 SM2 国密算法的融合探讨
5.1 SM2 替代 X25519 的可行性
GM/T 0003-2012 SM2 椭圆曲线公钥密码算法与 X25519 类似,都是基于椭圆曲线的密钥交换协议。理论上可以用 SM2 的 ECDH 功能替代 X25519/X448 实现 X3DH:
- 使用 SM2 密钥交换替代 DH1-DH4
- 保留 HKDF 密钥派生(将 SM3 作为哈希函数)
- 保留 XEdDSA 签名方案
5.2 实际挑战
- 协议兼容性:Signal 生态系统中广泛使用 X25519/X448,替换需要全网升级
- 安全证明:X3DH 的安全证明基于离散对数假设,SM2 的安全证明同样基于椭圆曲线离散对数问题,数学基础相似
- 性能:SM2 在软件实现中通常比 X25519 慢(取决于实现),但可通过硬件加速弥补
与双棘轮算法的协作
X3DH 建立的是初始会话密钥,后续的持续消息加密由 双棘轮(Double Ratchet) 算法负责:
X3DH(异步) → SK(初始共享密钥)
双棘轮(同步) → per-message keys(每消息密钥)初始化:
- Alice 使用 SK 初始化她的发送链和 Bob 的接收链
- Bob 使用 SK 初始化他的根密钥和 Alice 的接收链
- Alice 和 Bob 交换新的 DH 棘轮公钥,产生新的链密钥
- 每一条消息使用不同的消息密钥(对称棘轮)
- 每收到新的 DH 公钥就执行 DH 棘轮步骤(更换链密钥)
实现约束
7.1 服务器要求
- 必须能够存储 Bob 的公钥包
- 必须支持 OPKB 获取的 rate limiting
- 必须提供\"原子删除\"语义(取走 OPKB 时服务器必须删除副本,防止重放)
7.2 客户端要求
- 必须安全删除使用过的 OPKB 私钥
- 必须安全删除计算完成的 DH 输出
- 必须安全删除 EKA(Alice 发送完成后)
- Ed25519 签名密钥需要 CSPRNG(密码学安全随机数生成器)
7.3 标准与推荐参数
Signal 官方推荐:
- 曲线:X25519
- 哈希:SHA-256
- 签名:XEdDSA(基于 Curve25519 的 EdDSA 变体)
- KDF:HKDF-SHA256
总结
X3DH 代表了现代密码学协议设计的最高水平之一:
- 简洁而完备:核心协议仅包含 3-4 次 DH 交换和一次 KDF
- 安全目标明确:前向保密、后向保密、可否认性各有对应的密码学机制
- 实用性强:完美适配异步通信场景,无需接收方在线
- 可扩展性:已平滑演进到 PQXDH,为后量子时代做好准备
- 广泛部署:支撑 Signal、WhatsApp 等数十亿用户的端到端加密通信
参考来源
- Signal Specification: The X3DH Key Agreement Protocol (Revision 1, 2016-11-04)
- Signal Specification: The Double Ratchet Algorithm (Revision 4, 2025-11-04)
- Signal Specification: The PQXDH Key Agreement Protocol
- RFC 7748: Elliptic Curves for Security (X25519/X448)
- RFC 5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF)
- Kudla & Paterson, \"Modular Security Proofs for Key Agreement Protocols\", ASIACRYPT 2005