0 背景
在数字通信中,加密技术始终面临一个核心矛盾:如何安全地共享密钥。对称加密虽然效率高,但其依赖双方预先持有相同密钥的特性,在互联网开放环境下暴露了致命缺陷——若通过不安全信道传递密钥,可能被中间人截获并破解整个加密体系。经典的 Two Generals’ Problem 即隐喻了这种困境:如何在不可信信道中建立可信的密钥传输通道?这一矛盾直接催生了密码学领域的关键需求:安全密钥交换协议。
1976年 Diffie-Hellman 密钥交换协议的提出,标志着非对称加密技术的诞生彻底改变了游戏规则。其核心思想是通过数学单向函数(如离散对数或大数分解)构建公钥-私钥体系:用户公开公钥用于加密,保留私钥用于解密,从根本上解耦了密钥的分发与使用。这种公私钥分离机制使通信双方无需预先共享秘密,仅需交换公开信息即可协商出共享密钥,实现了密钥交换的前向安全性(即使长期私钥泄露,历史会话仍保密)。
随着即时通信、视频会议和物联网组网技术的普及,群组动态密钥协商成为现代加密领域的核心需求。传统非对称加密(如 RSA 或 ECDH)专注于点对点场景,而群组通信需确保多个参与方(如 10 人聊天室或千台设备组成的物联网集群)在动态变化(成员加入/退出)时,仍能高效协商共享密钥并实现前向保密(FS)与后向保密(BS)。这一需求在 GDPR 等数据合规框架下被进一步强化 —— 任何成员的状态变化均需触发密钥更新,以防止历史或未来消息泄露。
本文以 KEM -> RSA-KEM -> DHKEM -> TreeKEM 作为主线,解析 TreeKEM 的原理。
1 非对称加密
非对称加密(Asymmetric Cryptography)是一种基于数学难题的加密体系,其核心在于使用一对数学关联的密钥(公钥和私钥),使得加密和解密过程满足以下性质:
- 公钥加密,私钥解密:用公钥加密的数据只能用私钥解密。
- 单向函数特性:正向计算(加密)容易,逆向推导(从公钥破解私钥)在计算上不可行。
非对称加密的安全性依赖于 计算复杂性理论 中的数学难题,例如:
- 大整数质因数分解难题(RSA)
- 离散对数问题(ECC,椭圆曲线加密)
- 格基难题(Lattice-based Cryptography)
1.1 非对称加密的数学形式表达
非对称加密系统可定义为三元组 ( KeyGen , Enc , Dec ) (\text{KeyGen}, \text{Enc}, \text{Dec}) (KeyGen,Enc,Dec):
- 1.密钥生成:
- ( p k , s k ) ← KeyGen ( 1 λ ) (pk, sk) \leftarrow \text{KeyGen}(1^\lambda) (pk,sk)←KeyGen(1λ)
- λ \lambda λ 为安全参数。
- 2.加密算法:
- C ← Enc ( p k , M ) C \leftarrow \text{Enc}(pk, M) C←Enc(pk,M)
- 3.解密算法:
- M ← Dec ( s k , C ) M \leftarrow \text{Dec}(sk, C) M←Dec(sk,C)
- 满足:
- ∀ M ∈ M , Dec ( s k , Enc ( p k , M ) ) = M \forall M \in \mathcal{M},\ \text{Dec}(sk, \text{Enc}(pk, M)) = M ∀M∈M, Dec(sk,Enc(pk,M))=M
2 KEM
在密码安全领域,密钥封装机制 (Key Encapsulation Mechanism, KEM) 是一种用于安全传递对称密钥的密码学协议。其核心目标是通过公钥密码学的安全性,将对称密钥安全地传输给接收方,以便后续使用该对称密钥对数据进行高效加密。KEM 广泛应用于现代加密系统(如 TLS、MLS 等)
2.1 KEM的核心思想
- 密钥封装:发送方生成一个短期公钥(ephemeral public key)和对应的对称密钥,用接收方的公钥加密对称密钥(称为“封装”),接收方用私钥解密后获得对称密钥。
- 分离式加密:KEM仅负责传递对称密钥,实际数据加密由对称算法(如AES)完成,兼顾安全性与效率。
2.2 KEM 的基本流程
- 发送方 使用接收方的公钥将对称密钥封装成密文(称为“封装数据”)。
- 接收方 使用私钥解封装,恢复对称密钥,后续用该密钥加密实际数据(如文件、消息)。
2.3 KEM 的工作流程
典型的 KEM 流程分为三个阶段:密钥生成、封装和解封装。
- 1.密钥生成(KeyGen)
- 接收方 生成一对公私钥:
- 公钥( P K PK PK):公开共享,用于发送方封装密钥。
- 私钥( S K SK SK):保密存储,用于解封装。
- 数学基础:依赖特定困难问题(如离散对数、大数分解或格问题)。
- 接收方 生成一对公私钥:
- 2.密钥封装(Encap)
- 发送方:
- 生成一个临时对称密钥 K K K(或随机数种子)。
- 使用接收方的公钥 P K PK PK 将 K K K 加密为封装数据 (Ciphertext) C C C。
- 输出 C C C 和 K K K,用 K K K 加密实际数据。
- 关键点: K K K 由随机数生成,每次会话唯一。
- 发送方:
- 3.密钥解封装(Decap)
- 接收方:
- 使用私钥 S K SK SK 解封装 C C C,恢复出对称密钥 K K K 。
- 验证 K ′ K' K′ 的合法性(如通过哈希校验)。
- 使用 K ′ K' K′ 解密接收到的数据。
- 接收方:
2.4 KEM 的数学基础与算法类型
KEM 的具体实现取决于所依赖的数学难题:
- 1.经典 KEM
- RSAKEM(基于RSA):
- 数学基础:大整数分解问题。
- 特点:兼容传统系统,但无前向安全,密钥较长。
- DHKEM(基于Diffie-Hellman):
- 数学基础:离散对数问题(如椭圆曲线 ECDH)。
- 特点:支持前向安全,效率高(如 X25519)。
- RSAKEM(基于RSA):
- 2.后量子 KEM
- 格密码 KEM(如 CRYSTALS-Kyber):
- 数学基础:格上的 LWE(Learning With Errors)问题。
- 特点:抗量子攻击,密钥短,标准化进程领先(NIST PQC 候选算法)。
- 基于编码的 KEM(如 Classic McEliece):
- 数学基础:纠错码解码问题。
- 特点:安全性高,但计算和存储开销大。
- 格密码 KEM(如 CRYSTALS-Kyber):
- 3.其他类型
- 双线性配对 KEM:基于椭圆曲线上的双线性映射,支持高级功能(如属性加密)。
- 哈希基 KEM(如 SIDH):基于哈希函数的抗量子设计,但已被部分攻破。
2.5 KEM 与传统密钥交换的对比
特性 | KEM | 传统密钥交换(如 Diffie-Hellman) |
---|---|---|
目标 | 封装并传递对称密钥 | 直接协商共享密钥 |
输出形式 | 生成可传输的封装数据(Ciphertext) | 直接生成共享密钥,无显式传输结构 |
前向安全性 | 天然支持(依赖临时密钥) | 需额外设计(如临时 DH) |
协议耦合性 | 独立模块化设计,易集成 | 需与加密协议深度耦合 |
2.6 KEM 的实际应用
- 1.TLS 1.3 协议
- 密钥协商:使用 ECDHKEM(如 X25519)替代 RSA 密钥传输,提升前向安全性。
- 流程简化:客户端发送临时公钥,服务器响应封装数据,双方生成相同会话密钥。
- 2.HPKE(Hybrid Public Key Encryption)
- RFC 9180 标准:定义 KEM 为混合加密的核心组件,支持 DHKEM 和 RSAKEM。
- 应用场景:加密云存储数据、端到端加密通信(如 Signal 协议)。
- 3.后量子密码过渡
- 混合部署:同时使用经典 KEM(如 ECDH)和后量子 KEM(如 Kyber),逐步迁移至抗量子算法。
- NIST 标准化:CRYSTALS-Kyber 成为首个后量子 KEM 标准(2022年公布)。
3 RSA-KEM
3.1 RSA 加密方案介绍
RSA 是最早且广泛使用的非对称加密算法之一,由 Ron Rivest、Adi Shamir 和 Leonard Adleman 于 1977 年提出。其安全性基于大整数分解的数学难题,核心思想是通过公钥加密、私钥解密实现安全通信。
3.1.1 数学基础
- 1.大整数分解难题
- 定义:给定两个大质数 p p p 和 q q q,计算 n = p × q n = p \times q n=p×q 容易,但从 n n n 反向分解 p p p 和 q q q 在计算上不可行。
- 密钥强度: n n n 的二进制位数决定安全性(如 2048 位)。
- 2.欧拉定理
若 a a a 与 n n n 互质,即 gcd ( a , n ) = 1 \gcd(a, n) = 1 gcd(a,n)=1,则:
a ϕ ( n ) ≡ 1 m o d n a^{\phi(n)} \equiv 1 \mod n aϕ(n)≡1modn- 其中 ϕ ( n ) \phi(n) ϕ(n) 为欧拉函数,表示小于 n n n 且与 n n n 互质的正整数个数。
3.1.2密钥生成步骤
- 1.选择两个大质数
- 随机生成 p p p 和 q q q,满足 p ≠ q p \neq q p=q 且 p , q ≫ 1 p, q \gg 1 p,q≫1 。
- 2.计算模数
n
n
n
n = p × q n = p \times q n=p×q - 3.计算欧拉函数
ϕ
(
n
)
\phi(n)
ϕ(n)
ϕ ( n ) = ( p − 1 ) ( q − 1 ) \phi(n) = (p-1)(q-1) ϕ(n)=(p−1)(q−1) - 4.选择公钥指数
e
e
e
- 满足 1 < e < ϕ ( n ) 1 < e < \phi(n) 1<e<ϕ(n) 且 gcd ( e , ϕ ( n ) ) = 1 \gcd(e, \phi(n)) = 1 gcd(e,ϕ(n))=1 。
- 常用值: e = 65537 e = 65537 e=65537(平衡计算效率与安全性)。
- 5.计算私钥指数
d
d
d
-
d
d
d 是
e
e
e 在模
ϕ
(
n
)
\phi(n)
ϕ(n) 下的模反元素:
d ≡ e − 1 m o d ϕ ( n ) d \equiv e^{-1} \mod \phi(n) d≡e−1modϕ(n) - 通过扩展欧几里得算法求解。
-
d
d
d 是
e
e
e 在模
ϕ
(
n
)
\phi(n)
ϕ(n) 下的模反元素:
- 6.密钥对:
- 公钥: ( e , n ) (e, n) (e,n)
- 私钥: ( d , n ) (d, n) (d,n)
3.1.2 加密与解密流程
- 1.加密(使用公钥)
- 将明文
M
M
M 转换为整数,满足
0
≤
M
<
n
0 \leq M < n
0≤M<n,计算:
C ≡ M e m o d n C \equiv M^e \mod n C≡Memodn- 其中 C C C 为密文。
- 将明文
M
M
M 转换为整数,满足
0
≤
M
<
n
0 \leq M < n
0≤M<n,计算:
- 2.解密(使用私钥)
- 计算:
M ≡ C d m o d n M \equiv C^d \mod n M≡Cdmodn
- 计算:
3.1.3 安全性分析
-
1.依赖的数学难题
- 大整数分解问题:从 n n n 分解出 p p p 和 q q q 。
- RSA 问题:已知 C = M e m o d n C = M^e \mod n C=Memodn,求 M M M 。
-
2.攻击方式与防御
攻击类型 防御措施 暴力分解 ( n ) 使用足够长的密钥(≥2048 位) 侧信道攻击 恒定时间算法、掩码技术 量子计算攻击 迁移至抗量子算法(如格密码) -
3.填充方案(防止裸 RSA 攻击)
- PKCS#1 v1.5:旧标准,存在选择密文攻击风险。
- OAEP(Optimal Asymmetric Encryption Padding):结合哈希函数和随机化填充,增强安全性(推荐使用)。
3.2 RSA-KEM 介绍
RSA-KEM 是一种基于 RSA 的密钥封装协议,用于安全传输对称密钥。其设计目标是避免传统 RSA 加密的填充攻击风险,同时简化密钥交换流程。以下是其算法细节的完整解析:
3.2.1 算法定义与符号说明
- 密钥对:
- 公钥: ( e , n ) (e, n) (e,n),其中 n = p × q n = p \times q n=p×q, e e e 满足 gcd ( e , ϕ ( n ) ) = 1 \gcd(e, \phi(n)) = 1 gcd(e,ϕ(n))=1
- 私钥: ( d , n ) (d, n) (d,n),其中 d ≡ e − 1 m o d ϕ ( n ) d \equiv e^{-1} \mod \phi(n) d≡e−1modϕ(n)
- KDF(密钥派生函数):如 HKDF、PBKDF2,用于将随机数转换为对称密钥
- 安全参数: k k k(随机数长度,通常 k = ⌊ log 2 n ⌋ k = \lfloor \log_2 n \rfloor k=⌊log2n⌋)
3.2.2 算法分步流程
- 1.密钥生成(KeyGen)
- 输入:安全参数 λ \lambda λ(如 2048 位)
- 输出:RSA 密钥对 ( p k , s k ) (pk, sk) (pk,sk)
- 步骤:
- 1.生成两个大素数 p p p 和 q q q
- 2.计算 n = p × q n = p \times q n=p×q
- 3.计算 ϕ ( n ) = ( p − 1 ) ( q − 1 ) \phi(n) = (p-1)(q-1) ϕ(n)=(p−1)(q−1)
- 4.选择 e e e(通常为 65537)
- 5.计算 d ≡ e − 1 m o d ϕ ( n ) d \equiv e^{-1} \mod \phi(n) d≡e−1modϕ(n)
- 2.封装(Encapsulate)
- 输入:公钥 ( e , n ) (e, n) (e,n)
- 输出:密文 c c c,对称密钥 s s s
- 步骤:
- 1.生成随机数:
r ← R { 1 , 2 , . . . , n − 1 } r \xleftarrow{R} \{1, 2, ..., n-1\} rR{1,2,...,n−1}- 要求 gcd ( r , n ) = 1 \gcd(r, n) = 1 gcd(r,n)=1(概率极高,可不显式检查)
- 2.计算封装密文:
c = r e m o d n c = r^e \mod n c=remodn - 3.派生对称密钥:
s = KDF ( r ) s = \text{KDF}(r) s=KDF(r)- 典型 KDF:HKDF-SHA256,输出长度匹配对称算法(如 AES-256 需 32 字节)
- 1.生成随机数:
- 3.解封装(Decapsulate)
- 输入:私钥 ( d , n ) (d, n) (d,n),密文 c c c
- 输出:对称密钥 s s s
- 步骤:
- 1.恢复随机数:
r ′ = c d m o d n r' = c^d \mod n r′=cdmodn - 2.验证一致性(可选):
- 检查 gcd ( r ′ , n ) = 1 \gcd(r', n) = 1 gcd(r′,n)=1
- 重新计算 c ′ = ( r ′ ) e m o d n c' = (r')^e \mod n c′=(r′)emodn,确认 c ′ = c c' = c c′=c
- 3.派生对称密钥:
s ′ = KDF ( r ′ ) s' = \text{KDF}(r') s′=KDF(r′)
- 1.恢复随机数:
RSA-KEM 通过以下创新解决了传统 RSA 加密的缺陷:
- 消除填充攻击面:直接封装随机数,无需复杂填充规则
- 简化安全分析:安全性仅依赖 RSA 问题和 KDF 强度
- 高效密钥交换:特别适合与对称加密组成混合系统
其设计哲学体现了现代密码学的核心原则:通过模块化组合简单安全的原语(RSA + KDF)构建复杂的安全协议。
4 DHKEM
4.1 DH 介绍
Diffie-Hellman(DH)密钥交换协议是一种允许双方在不安全信道上安全协商共享密钥的算法,由Whitfield Diffie和Martin Hellman于1976年提出。其核心基于离散对数问题,无需预共享密钥即可建立安全通信。
4.1.1 DH 核心原理
-
1.数学基础
- 离散对数问题(DLP)
- 给定大素数 ( p )、生成元 ( g )(( 1 < g < p )),已知 ( g^a \mod p ) 和 ( g^b \mod p ),计算 ( g^{ab} \mod p ) 在计算上不可行。
- 公式推导
- Alice 私钥 a a a,公钥 A = g a m o d p A = g^a \mod p A=gamodp
- Bob 私钥 b b b,公钥 B = g b m o d p B = g^b \mod p B=gbmodp
- 共享密钥: K = A b m o d p = B a m o d p = g a b m o d p K = A^b \mod p = B^a \mod p = g^{ab} \mod p K=Abmodp=Bamodp=gabmodp
- 离散对数问题(DLP)
-
2.密钥交换流程
- 使用时序图表示的 Diffie-Hellman (DH) 密钥交换算法:
ECDH(Elliptic Curve Diffie-Hellman)是基于椭圆曲线密码学的密钥交换协议,通过椭圆曲线离散对数问题(ECDLP)实现安全密钥协商。相比传统DH,它在相同安全性下密钥更短、计算更快,广泛应用于TLS、SSH和区块链等场景。
4.1.2 DH 算法变种
- 1.经典DH(静态DH)
- 特点:使用固定的长期密钥对,无前向安全性。
- 适用场景:兼容旧系统或低安全需求场景。
- 2.Ephemeral DH(DHE,临时DH)
- 特点:每次会话生成临时密钥对,提供前向安全性。
- TLS应用:如
DHE_RSA
或ECDHE_RSA
密钥交换。 - 优点:长期私钥泄露不影响历史会话安全。
- 3.椭圆曲线DH(ECDH)
- 数学基础:基于椭圆曲线离散对数问题(ECDLP)。
- 优势:
- 更短密钥(256位 ECC ≈ 3072位 RSA)
- 更高计算效率(适合移动设备)。
- 曲线示例:NIST P-256、Curve25519。
目前在生产环境中多产用 ECDHE 作为 DH 算法的首选,所以本文后面提到的 DH 算法默认表示使用 ECDHE 算法。
4.2 DHKEM 介绍
DHKEM 是一种基于Diffie-Hellman密钥交换协议构建的密钥封装机制(KEM),属于现代密码学中混合加密系统的核心组件。其目标是将非对称加密的高安全性与对称加密的高效性结合,实现安全密钥分发与数据加密的分离。
4.2.1 算法流程(以 HPKE-DHKEM 为例)
- 1.参数定义
- DH 群组:选择离散对数群(如
FFDHE2048
)或椭圆曲线群(如P-256
)。 - KDF:密钥派生函数(如
HKDF-SHA256
)。 - AEAD:认证加密算法(如
AES-GCM
)。
- DH 群组:选择离散对数群(如
- 2.密钥生成
- 接收方(Bob):
- 1.生成长期静态密钥对:
(sk_B, pk_B) = DH.KeyGen()
。 - 2.发布公钥
pk_B
。
- 1.生成长期静态密钥对:
- 发送方(Alice):
1.生成临时密钥对:(sk_E, pk_E) = DH.KeyGen()
。
- 接收方(Bob):
- 3.封装(Encapsulate)
1.计算共享密钥:
d h = D H ( s k E , p k B ) = D H ( s k B , p k E ) dh = DH(sk_E, pk_B) = DH(sk_B, pk_E) dh=DH(skE,pkB)=DH(skB,pkE) - 2.派生对称密钥:
k e y = K D F ( d h , i n f o = "HPKE-DHKEM" , l e n = 32 ) key = KDF(dh, info=\text{"HPKE-DHKEM"}, len=32) key=KDF(dh,info="HPKE-DHKEM",len=32) - 3.封装输出:
- 密文:
ct = pk_E
(无需加密,仅传输公钥) - 对称密钥:
key
- 密文:
- 4.解封装(Decapsulate)
-
- 接收方使用
sk_B
和收到的pk_E
:
d h ′ = D H ( s k B , p k E ) dh' = DH(sk_B, pk_E) dh′=DH(skB,pkE)
- 接收方使用
- 2.派生对称密钥:
k e y ′ = K D F ( d h ′ , i n f o = "HPKE-DHKEM" , l e n = 32 ) key' = KDF(dh', info=\text{"HPKE-DHKEM"}, len=32) key′=KDF(dh′,info="HPKE-DHKEM",len=32)
-
4.2.2 DHKEM 数学正确性
由于 DH 的交换律:
D
H
(
s
k
E
,
p
k
B
)
=
g
s
k
E
⋅
s
k
B
=
D
H
(
s
k
B
,
p
k
E
)
DH(sk_E, pk_B) = g^{sk_E \cdot sk_B} = DH(sk_B, pk_E)
DH(skE,pkB)=gskE⋅skB=DH(skB,pkE)
因此:
k
e
y
=
K
D
F
(
g
s
k
E
⋅
s
k
B
)
=
k
e
y
′
key = KDF(g^{sk_E \cdot sk_B}) = key'
key=KDF(gskE⋅skB)=key′
4.2.3 DHKEM 与 RSA-KEM 的对比
特性 | DHKEM | RSA-KEM |
---|---|---|
数学基础 | 基于Diffie-Hellman密钥交换(离散对数问题或椭圆曲线离散对数问题) | 基于RSA加密(大整数分解问题) |
密钥类型 | 通常使用临时密钥对(Ephemeral Key) | 依赖长期静态密钥对 |
前向安全性 | 天然支持前向安全(每次会话生成新临时密钥) | 无前向安全(需额外设计如结合临时密钥) |
抗量子计算能力 | 若使用椭圆曲线(如X25519),目前无已知量子攻击直接破解;后量子变体(如CSIDH)可升级 | 完全依赖大数分解,易受Shor算法攻击(量子不安全) |
密钥长度 | 短(如X25519仅需256位) | 长(如RSA-3072需要3072位) |
计算效率 | 高(椭圆曲线运算速度快) | 低(大数模幂运算开销大) |
标准化应用案例 | TLS 1.3、HPKE(RFC 9180)、Signal协议 | 旧版TLS(如TLS 1.2)、传统PKI系统 |
5 TreeKEM
早期群组密钥管理方案(如“星型拓扑”或链式 Diffie-Hellman 扩展)面临严峻挑战:
- 计算复杂度高:n 个成员的群组需 O(n) 次双边密钥交换(如基于ECDH的 “n-1次握手”),导致密钥更新延迟随规模线性增长;
- 通信开销大:每次成员变动需广播大量密钥更新消息(如RSA加密的密钥包),难以支持大规模或低带宽场景;
- 动态性不足:多数方案需全局同步或中心化协调,无法高效处理高频成员变更。
2018年提出的TreeKEM(Tree-based Key Encapsulation Mechanism)通过树形结构与密钥封装机制(KEM)的融合,重新定义了群组密钥交换的底层逻辑:
- 树状分层:将群组成员组织为二叉树,每个节点关联密钥材料,密钥更新仅需修改受影响路径,复杂度降至O(log n);
- 封装递推:通过KEM(如HPKE或Kyber)实现密钥材料的单向扩散,成员仅需解密父节点即可推导最新群密钥,无需全量同步;
- 抗量子设计:兼容后量子KEM算法(如CRYSTALS-Kyber),为量子计算时代提供前瞻性防护。
5.1 前置内容
5.1.1 DeriveKeyPair
DeriveKeyPair 是 Hybrid Public Key Encryption (HPKE) 协议中的关键操作,用于确定性生成密钥对。其核心目标是通过预定义的输入参数生成可复现的密钥对,避免依赖随机数生成器,提升密钥管理的可控性和安全性。
算法实现原理
- 1.输入参数
- 种子(Seed):随机或伪随机数,作为密钥生成的熵源。
- 密钥派生函数(KDF):如 HKDF,用于扩展种子并生成密钥材料。
- 算法标识符:如椭圆曲线类型(P-256、X25519 等),决定密钥格式。
- 2.密钥派生流程
- 输入种子 → KDF 扩展 → 生成密钥字节 → 格式化为私钥 → 计算公钥
与 GenerateKeyPair 不同,DeriveKeyPair 通过固定的 IKM 可以生成确定性的 KeyPair,是组群通信中,是保证所有参与者具有相同公钥视图的重要手段。
5.1.2 KEM 算法的调整
根据 RFC 9180 Section 4.1 对 KEM 的定义:
def Encap(pkR):
skE, pkE = GenerateKeyPair()
dh = DH(skE, pkR)
enc = SerializePublicKey(pkE)
pkRm = SerializePublicKey(pkR)
kem_context = concat(enc, pkRm)
shared_secret = ExtractAndExpand(dh, kem_context)
return shared_secret, enc
def Decap(enc, skR):
pkE = DeserializePublicKey(enc)
dh = DH(skR, pkE)
pkRm = SerializePublicKey(pk(skR))
kem_context = concat(enc, pkRm)
shared_secret = ExtractAndExpand(dh, kem_context)
return shared_secret
每次 Encap()
操作由于有 ephemeral key pair 的参与,计算出的 shared_secret
都是随机的,而组群通信中,通常要求同一个 epoch 周期内,组群内共享同一个 shared_secret
,所以在 TreeKEM 中需要将 KEM 改进一下,改进的思路有两种:
- 第一种思路是将
skE, pkE = GenerateKeyPair()
替换为skE, pkE = DeriveKeyPair(ikm)
从而固定 ephemeral key pair ,这样对算法的改动最小,但是破坏了算法的前向安全性,通常不用在生产环境中; - 另外一种思路是改造,
Encap(pkR) -> shared_secret, enc
生成的shared_secret
作为对称加密的密钥,加密真正的sharedsecret'
具体细节可以参考 RFC 9180 Section 6 -> Single-Shot APIsdef Seal<MODE>(pkR, info, aad, pt, ...): enc, ctx = Setup<MODE>S(pkR, info, ...) ct = ctx.Seal(aad, pt) return enc, ct def Open<MODE>(enc, skR, info, aad, ct, ...): ctx = Setup<MODE>R(enc, skR, info, ...) return ctx.Open(aad, ct)
5.2 Ratchet Tree 介绍
Ratchet Tree (棘轮树) 是一种基于树形结构的密钥管理机制,旨在为动态组群通信提供高效的端到端加密 (E2EE) 和前后向安全性。其核心思想是通过树形结构和层次化密钥派生,减少密钥更新的通信开销,同时支持群组成员的动态加入、离开和密钥轮换。
5.2.1 Ratchet Tree 中的几个重要概念
参考 RFC 9420 Section 4 -> Ratchet Tree Concepts,Ratchet Tree 的演进和同步依赖一下几个重要的概念。
5.2.1.1 节点的解析 (Resolution)
节点的解析是节点下方最近的非空白节点的 (深度优先 and 左优先) 枚举。
- 非空白节点的解析为节点本身和所有未合并叶子节点的列表;
- 空白叶节点的解析度为空;
- 空白中间节点的解析是将其左子节点的解析与右子节点的解析按顺序连接起来;
...
/
_
______|______
/ \
X[B] _
__|__ __|__
/ \ / \
_ _ Y _
/ \ / \ / \ / \
A B _ D E F _ H
0 1 2 3 4 5 6 7
以上面这个树列举关于节点解析度的规则:
- 节点 X 的解析列表为 [X, B].
- 2 号和 6 号叶子节点的解析列表为 [].
- 根节点的解析列表为 [X, B, Y, H].
5.2.1.2 节点的路径
- 直接路径 (Direct path)
- 节点的直接路径是该节点到根节点路径节点的集合,不包括当前节点;
- 共同路径 (Copath)
- 节点的共同路径为该节点的兄弟节点和该节点直接路径上所有节点的兄弟节点的集合,不包括根节点;
- 过滤直接路径 (Filtered Dicrect Path)
- 过滤直接路径:在直接路径中,除了根节点,如果一个节点的兄弟节点解析为空则删除该节点;
下面的表示中,空白节点以 “_” 表示,但在等号后面分配了一个标签以供参考:
W = root
|
.-----+-----.
/ \
_=U Y
| |
.-+-. .-+-.
/ \ / \
T _=V X _=Z
/ \ / \ / \ / \
A B _ _ E F G _=H
0 1 2 3 4 5 6 7
Node | Direct path | Copath | Filtered Direct Path |
---|---|---|---|
A | T, U, W | B, V, Y | T, W |
B | T, U, W | A, V, Y | T, W |
E | X, Y, W | F, Z, U | X, Y, W |
F | X, Y, W | E, Z, U | X, Y, W |
G | Z, Y, W | H, X, U | Y, W |
5.3 Ratchet Tree 操作
参考 RFC 9420 Section 7 -> Ratchet Tree Operations ,我们详细分析 Ratchet Tree 的演进和同步机制。
5.3.1 Ratchet Tree Evolution
一个纪元的棘轮树描述了该纪元中一个组的成员资格,提供了可用于加密该组子集的公钥加密(HPKE)密钥以及验证成员的信息。为了反映组成员从一个时代到下一个时代的变化,对棘轮树进行了相应的更改。在本节中,我们将描述树的内容和所需的操作。
每当成员发起纪元更改(即提交)时,他们可能需要刷新其叶子和叶子直接路径上节点的密钥对,以保持前向保密性和妥协后的安全性。
发起纪元更改的成员使用以下过程生成新的密钥对。该程序的设计方式允许组成员有效地将新的密钥传递给其他组成员。
成员沿其直接路径更新节点,如下所示:
清空从叶子到根的直接路径上的所有节点。
为叶子生成一个新的 HPKE 密钥对。
生成一系列路径秘密,每个节点对应叶子过滤后的直接路径,如下所示。在此设置中,path_secret[0] 指代过滤后的直接路径中的第一个父节点,path_secrit[1] 指代第二个父节点等。
path_secret[0] is sampled at random
path_secret[n] = DeriveSecret(path_secret[n-1], "path")
计算HPKE密钥对(node_priv、node_pub)的序列,叶子直接路径上的每个节点对应一个密钥对,如下所示。
node_secret[n] = DeriveSecret(path_secret[n], "node")
node_priv[n], node_pub[n] = KEM.DeriveKeyPair(node_secret[n])
节点秘密作为临时中间秘密导出,因此每个秘密只用于一种算法:路径秘密用作 DeriveSecret 的输入,节点秘密用作 DerieKeyPair 的输入。
例如,假设有一个有四个成员的群,其中 C 在 Z 处是一个未合并的叶子:
Y
|
.-+-.
/ \
X Z[C]
/ \ / \
A B C D
0 1 2 3
如果成员 B 随后基于秘密 “leaf_secret” 生成 UpdatePath,那么它将生成以下路径秘密序列:
path_secret[1] ---> node_secret[1] -------> node_priv[1], node_pub[1]
^
|
|
path_secret[0] ---> node_secret[0] -------> node_priv[0], node_pub[0]
^
|
|
leaf_secret ------> leaf_node_secret --+--> leaf_priv, leaf_pub
| |
'-------. .-------'
|
leaf_node
应用 UpdatePath 后,树将具有以下结构:
node_priv[1] --------> Y'
|
.-+-.
/ \
node_priv[0] ----> X' Z[C]
/ \ / \
A B C D
^
leaf_priv -----------+
0 1 2 3
5.3.1 Ratchet Tree Synchronous
- 计算该节点 copath 节点的解析,整合为节点列表;
- 对列表中的每个节点,使用该节点的公钥加密其直接路径上的 path_secret;
在生成新的密钥材料并将其应用于更新其本地树状态后,生成器在 Commit 消息中将此更新广播给组的其他成员,这些成员应用此更新以保持其对树的本地视图与发送方的视图同步。更具体地说,当成员对树进行更改(例如添加或删除成员)时,它会传输一个 UpdatePath,其中包含一组公钥和其叶子的过滤直接路径中的中间节点的加密路径秘密。组中的其他成员使用这些值来更新他们对树的视图,将他们的树副本与发送者的对齐。
UpdatePath 包含发送方叶子的过滤直接路径中每个节点的以下信息,包括根:
- 节点的公钥
- 与节点对应的路径秘密的一个或多个加密副本
给定节点的路径秘密值被加密到以父节点的未更新子节点(即发送方叶子节点共路径上的子节点)为根的子树中。在未更新子项的解析中,每个公钥的路径秘密都有一个加密。
该组的成员通过计算其叶节点和沿其过滤后的直接路径的节点的新值来更新其直接路径,如下所示:
- 清空发送方叶子直接路径上的所有节点。
- 为发送方过滤后的直接路径上的节点计算更新的路径机密和公钥。
- 生成一个与过滤后的直接路径长度相同的路径秘密序列,如第7.4节所述。
- 对于过滤后的直接路径中的每个节点,将节点的公钥替换为从相应的路径
secret-path_secret[n]
导出的node_pub[n]
值。
- 为过滤后的直接路径上的节点和发送方的叶子节点计算新的父哈希值。
- 更新发件人的叶子节点。
- 将 leaf_node_source 设置为提交。
- 将 encryption_key 设置为新采样密钥对的公钥。
- 将父哈希设置为叶子的父哈希。
- 用新内容重新签署叶子节点。
由于新的叶子节点有效地更新了组中的现有叶子节点,因此它必须遵守与更新提案中使用的叶子节点相同的限制(leaf_node_source 除外) 。应用程序可以指定叶节点的其他更改,例如提供新的签名密钥、更新的功能或不同的扩展。
然后,成员对组的路径秘密进行加密。对于成员的过滤直接路径中的每个节点,成员将采取以下步骤:
- 计算发送方共路径上节点子节点的解析度(不在发送方直接路径上的子节点)。必须将同一 Commit 中添加的任何新成员(来自 Add Propersal)排除在本决议之外。
- 对于解析中的每个节点,使用解析节点的公钥对直接路径节点的路径秘密进行加密。
UpdatePath 的接收者执行相应的步骤。首先,收件人将UpdatePath合并到树中:
-
清空发送方叶子的直接路径上的所有节点。
-
对于发送方叶子的过滤直接路径上的所有节点,
- 将公钥设置为 UpdatePath 中的公钥。
- 将未合并的叶子列表设置为空列表。
-
计算发送方过滤直接路径中节点的父哈希,并验证叶子节点的 parent_hash 字段是否与其过滤直接路径上第一个节点的父散列匹配。
请注意,这些哈希是从根到叶计算的,因此每个哈希都包含其上方的所有非空节点。根节点的父哈希总是有一个零长度的哈希。
其次,接收方解密路径秘密:
- 在筛选的直接路径中标识一个节点,该节点的接收方位于未更新子节点的子树中。
- 在共路径节点的解析中标识接收方拥有私钥的节点。
- 使用解析节点的私钥解密共路径节点父节点的路径秘密。
- 使用上述算法在发送方的过滤直接路径中导出该节点祖先的路径秘密。
- 从路径秘密中导出节点秘密和节点密钥对。
- 验证派生公钥是否与 UpdatePath 中发送的相应公钥相同。
- 将导出的私钥存储在相应的棘轮树节点中。
例如,为了传达第7.4节中描述的示例更新,节点B的成员将传输以下值:
Public Key | Ciphertext(s) |
---|---|
node_pub[1] | E(pk(Z), path_secret[1]), E(pk©, path_secret[1]) |
node_pub[0] | E(pk(A), path_secret[0]) |
在该表中,值 node_pub[i] 表示从 node_secret[i] 导出的公钥,pk(X) 表示节点 X 的当前公钥,E(K, S) 表示路径秘密 S 到公钥 K 的公钥加密 (使用 HPKE)。
节点 A 处的接收者将解密 E(pk(A), path_secret[0]) 以获得 path_secret [0] ,然后使用它来导出 path_secret[1] 以及由此产生的节点秘密和密钥对。因此,根据树不变量,A 将拥有节点 X’ 和 Y’ 的私钥。
类似地,节点 D 处的接收者将解密 E(pk(Z), path_secret[1]) 以获得 path_secret[1],然后使用它来导出节点 Y’ 的节点秘密和密钥对。为了保持树的不变性,节点 D 不接收节点 X’ 的私钥,因为 X’ 不是 D 的祖先。
处理更新后,每个收件人必须删除过时的密钥材料,具体如下:
- 用于导出每个更新的节点密钥对的路径密钥和节点密钥。
- 被更新替换的每个过时的节点密钥对。
6 结语
在数字化协作与隐私保护需求并行的今天,TreeKEM 凭借其独特的树状密钥管理架构,为动态群组通信的安全性问题提供了革命性的解决方案。通过将密钥更新的计算与通信开销降至对数级别,TreeKEM 不仅实现了高效的前向与后向安全(Forward/Backward Secrecy),还通过灵活的树结构设计,完美适配成员频繁变动的现代协作场景(如即时通讯群组、物联网设备网络)。
当前,随着 MLS(Messaging Layer Security)协议 的标准化推进,TreeKEM 作为其核心组件,已在 Signal、WhatsApp 等主流通信平台中展现出强大的实践价值。然而,面对量子计算威胁与超大规模群组(如万人级会议系统)的挑战,如何进一步优化树结构平衡策略、融合后量子密码学(如基于格的密钥封装),仍是未来研究的关键方向。
可以预见,在隐私保护需求日益迫切的万物互联时代,TreeKEM 将持续推动安全通信技术的边界,成为构建可信数字协作生态的基石。其设计哲学——“以数学之美,平衡安全与效率”——也将为更多密码学协议提供灵感,重塑我们对“安全”二字的认知与实现方式。