- • ECDSA / EdDSA / curve25519 长期密钥对
- • 用户注册时一次性生成, 通常永不更换
- • 用途: 验证身份 (我就是我), 给 SPK 签名
- • 失去 IK = 身份被盗 (但不影响过去消息: 前向安全)
- • 周期性轮换 (典型: 每周 / 每月)
- • 由 IK 签名, 证明"是 Bob 同意的"
- • 提供"OTK 用尽时的备用握手能力"
- • 旧 SPK 保留一段时间以解密延迟到达消息
- • 客户端预先批量生成 (e.g., 100 个), 上传 server
- • server 每发出一个消耗一个
- • 提供额外的前向安全 + 防 replay
- • 需要客户端定期补充 (详见 #09)
- • 发送方在每次会话首条消息时生成
- • 公钥 EK_A^pub 随消息发出, 私钥用完丢弃
- • 提供单次会话隔离 (跨会话不可关联)
- • 区分 ^pub / ^priv 至关重要 (常见混淆点)
💡 一句话理解:
X3DH = "三层密钥 + 一次握手"——
IK 验身份, SPK 保可用, OTK 加前向, EK 隔会话。
4 个 DH 计算把这 4 类密钥两两混合, 任一类被替换 / 缺失都会丢失对应的安全属性 — 这是为什么 Signal 偏要做"3DH+1"而不是简单的 1DH。
📚 基础知识速查 · Reference
不熟悉以下底层概念? 这里是 30 秒回顾。
签名EdDSA / Ed25519
椭圆曲线数字签名算法, Curve25519 上的签名版本。SPK 用 IK 签名, 证明"是该用户授权上传的"。
sig = Ed25519.sign(IK_priv, SPK_pub)
设计4-way DH 组合
4 次独立 DH 计算的 hash 拼接, 确保任何一方的密钥被替换都会改变 SharedSec。任一 DH 失效即整体失效。
SharedSec = HKDF(DH₁ ‖ DH₂ ‖ DH₃ ‖ DH₄)
数据结构PreKey Bundle
服务端发给请求方的"握手包"。包含发布方所有公钥 + SPK 的签名, 让发起方一次性获取 X3DH 所需输入。
{ IK^pub, SPK^pub, sig, OTK^pub }
命名公私钥语法约定
本图谱中用 ^pub / ^priv 上下标区分公私钥。这是常见的混淆点 — 务必记清楚谁参与 DH。
K^pub = 公钥可上行
K^priv = 私钥仅本地