4. 混合密钥交换原理

在 TLS 1.3 的密钥交换阶段,客户端与服务器最终要得到一份只有双方知道的共享秘密,再由它派生出握手密钥与应用流量密钥。混合密钥交换(Hybrid Key Exchange)的核心思想是:同时运行一条经典密钥交换(通常是 ECDHE)和一条后量子 KEM(如 ML-KEM/Kyber),把两路共享秘密拼接后再统一派生密钥。这样,只要其中任意一条仍然安全,整个握手就不会被攻破——这正是“混合”的价值所在。

需要先厘清一个容易混淆的点:ECDHE 与 KEM 的数学结构并不相同。ECDHE 是双方各自生成临时密钥对、交换公钥、各自用私钥与对方公钥计算出同一个共享点;而 KEM 是“封装/解封装”模型:一方用对方公钥封装出一个密文和共享秘密,另一方用私钥解封装得到同一共享秘密。TLS 1.3 的 key_share 扩展天然适合承载 ECDHE 的临时公钥,而 PQC KEM 则通过新的命名组(如 X25519MLKEM768)把 KEM 公钥/密文嵌入到同一握手机制中。

组合方式:拼接而非嵌套

混合密钥交换最常见的组合方式是秘密拼接(concatenation),而不是把两路秘密再做一次异或或哈希嵌套。以 IETF 定义的 X25519MLKEM768 为例,其共享秘密按固定顺序拼接:

shared_secret = ML-KEM-768_shared_secret || X25519_shared_secret
              = 32 字节 || 32 字节
              = 64 字节

顺序非常关键:先 PQC 后经典,或先经典后 PQC,必须由协议规范固定,双方不能各自理解不同。拼接后的 64 字节秘密再交给 TLS 1.3 的 HKDF-Extract,作为 Early Secret 或 Handshake Secret 的输入熵。也就是说,混合发生在“秘密”层面,而不是在“算法”层面——两条算法各自独立运行,互不干扰,最后才汇合。

拼接顺序、长度、命名组 ID 都属于互操作约定。实现时若顺序写反,双方会派生出不同密钥,握手会在 Finished 校验阶段失败,而不是在密钥交换阶段报错,排障时要特别注意。

共享密钥派生链路

拼接后的共享秘密进入 TLS 1.3 的密钥派生树。以标准握手为例,派生路径大致为:

HKDF-Extract(salt=0, IKM=PSK 或 0)
        → Early Secret
HKDF-Extract(salt=Early Secret, IKM=ECDHE||KEM 共享秘密)
        → Handshake Secret
HKDF-Expand-Label(Handshake Secret, "c hs traffic", transcript_hash)
        → client_handshake_traffic_secret
HKDF-Expand-Label(Handshake Secret, "s hs traffic", transcript_hash)
        → server_handshake_traffic_secret
HKDF-Extract(salt=Handshake Secret, IKM=0)
        → Master Secret
HKDF-Expand-Label(Master Secret, "c ap traffic", transcript_hash)
        → client_application_traffic_secret_0

可以看到,混合共享秘密只影响 Handshake Secret 这一层,之后所有握手流量密钥、主密钥、应用流量密钥都由它逐级派生。因此,只要混合共享秘密不同,整棵密钥树都会不同;反之,只要双方拼接结果一致,后续派生就完全一致。这也解释了为什么混合密钥交换的兼容性风险主要集中在“秘密拼接与命名组协商”这一小段,而不是整个密钥派生流程。

安全边界:混合不等于绝对安全

混合密钥交换的安全边界可以用一句话概括:整体安全性不低于两条算法中较强的一条,但也不高于两条算法中较弱的一条被攻破后的最坏情况。更准确地说:

  • 若 ECDHE 被量子计算机攻破、ML-KEM 仍安全,则共享秘密仍保密,握手安全;
  • 若 ML-KEM 被未来密码分析攻破、ECDHE 仍安全,则共享秘密仍保密,握手安全;
  • 若两者同时被攻破,则混合失效——这正是“混合”无法覆盖的边界;
  • 若实现层出现拼接顺序错误、长度截断、随机数复用等工程缺陷,则数学安全性再高也无法挽救。

此外,混合密钥交换只保护密钥交换阶段的机密性,不自动提供身份认证的抗量子能力。如果服务器证书仍使用 RSA 或 ECDSA 签名,攻击者仍可在量子环境下伪造证书。因此工程上通常把“混合密钥交换”与“PQC 证书/签名”分开评估:前者解决“会话密钥不被量子解密”,后者解决“身份不被量子伪造”。

工程实现中的关键观察点

在 OpenSSL 3.5+ 或 BoringSSL 等支持混合组的实现中,可以通过以下方式观察混合是否真正生效:

# 客户端指定混合组发起连接
openssl s_client -connect example.com:443 \
  -groups X25519MLKEM768 -tls1_3

# 观察握手输出中的 key_share 与命名组
# 若显示 "Peer Temp Key: X25519MLKEM768" 则混合已启用
# 若回退到 X25519 或 P-256,则说明服务端未协商混合组

判断依据是:协商结果中的命名组必须是混合组 ID,而不是单独的 X25519 或 ML-KEM。如果客户端发送了混合 key_share,但服务端只支持经典组,TLS 1.3 会通过 HelloRetryRequest 或直接选择经典组完成握手——此时连接仍然成功,但后量子保护并未生效。工程上应把“命名组是否为混合组”作为部署验收的硬性指标,而不是只看“握手是否成功”。

混合密钥交换:ECDHE + ML-KEM 组合与共享密钥派生 客户端 Client ECDHE 临时密钥对 (sk_c, pk_c) X25519 ML-KEM 密钥对 (dk_c, ek_c) ML-KEM-768 本地计算 ss_ec = ECDH(sk_c, pk_s) ss_kem = Decap(dk_c, ct) 拼接 → 64B 服务器 Server ECDHE 临时密钥对 (sk_s, pk_s) X25519 ML-KEM 封装 (ct, ss_kem) Encap(ek_c) 本地计算 ss_ec = ECDH(sk_s, pk_c) ss_kem = Encap 输出 拼接 → 64B pk_c (X25519 公钥) pk_s + ct (KEM 密文) 双方各自得到相同 64B 共享秘密 HKDF-Extract → Handshake Secret → 握手/应用流量密钥 安全边界 任一算法安全 → 会话安全 不覆盖 证书签名抗量子

最后需要强调:混合密钥交换的部署验收不能只看“连接是否成功”。真正要确认的是三件事——命名组协商结果是否为混合组、共享秘密拼接顺序是否符合规范、密钥派生链路是否与标准 TLS 1.3 一致。只有这三项同时成立,才能说后量子保护真正生效,而不是仅仅完成了一次“看起来正常”的握手。