# 后量子 TLS：ML-KEM 混合密钥交换与 Merkle 树证书

> 2026 年的后量子 TLS 到底是什么：浏览器已在用的混合 ML-KEM 密钥交换、后量子证书为什么难、Merkle 树证书如何解决体积问题。

Source: https://ssl.sh/zh/learn/post-quantum-tls/
Last updated: 2026-11-10

今天生产环境里的“后量子 TLS”指的就是一件事：混合密钥交换 X25519MLKEM768。Chrome、Edge 等客户端遇到支持它的服务器时已经默认使用。它保护的是流量的机密性，防的是“现在录下、将来用量子计算机解密”。证书和签名仍是传统算法，因为后量子签名太大；Web 对此的方案是 Merkle 树证书，截至 2026 年 11 月仍处于实验阶段。

## 为什么先改密钥交换

密钥交换最紧迫，原因是“先存后解”（harvest now, decrypt later）：今天录下的流量，等到能破解密码的量子计算机出现后就可以解密。Shor 算法能同时攻破 RSA 和椭圆曲线密码，2026 年一次 TLS 会话的 ECDHE 密钥一旦被算出，它加密的所有内容都会暴露。

签名不一样。伪造签名只在证书有效、攻击者实时在线时才有用，未来造出的量子计算机没法回过头去冒充过去某次连接里的服务器。

| TLS 的部分 | 今天的传统算法 | 量子威胁 | 紧迫程度 |
|---|---|---|---|
| 密钥交换（会话机密性） | X25519 或 P-256 上的 ECDHE | 录下的流量日后被解密 | 现在：今天截获的数据已有风险 |
| 服务器认证（证书、CertificateVerify） | RSA、ECDSA | 量子计算机出现后可实时冒充 | 要在量子计算机出现前完成，并具备防降级能力 |
| 对称加密 | AES-128/256-GCM、ChaCha20-Poly1305 | Grover 算法大约把有效强度减半 | 低：AES-256 乃至 AES-128 实际上都够用 |

国密 SM2 同样基于椭圆曲线，面临同样的量子威胁。国内也已启动新一代商用密码算法（包括抗量子算法）的研究和征集，但截至 2026 年 11 月还没有进入 TLS 实际部署。

## 标准：ML-KEM、ML-DSA 与 SLH-DSA

NIST 在 2024 年 8 月 13 日发布了首批三项后量子标准，它们在 TLS 里分工不同。

| 标准 | 算法 | 前身 | 在 TLS 中的角色 |
|---|---|---|---|
| FIPS 203 | ML-KEM（512、768、1024） | CRYSTALS-Kyber | 密钥交换（密钥封装） |
| FIPS 204 | ML-DSA（44、65、87） | CRYSTALS-Dilithium | 签名：证书、CertificateVerify |
| FIPS 205 | SLH-DSA | SPHINCS+ | 保守的基于哈希的签名，体积很大 |

TLS 1.3 密钥交换方面，RFC 10024（2026 年 8 月）定义了三个混合组：`X25519MLKEM768`（0x11EC）、`SecP256r1MLKEM768` 和 `SecP384r1MLKEM1024`。更早的部署用的是 `X25519Kyber768Draft00`（0x6399），那是 Kyber 标准化之前的版本，浏览器已经不再支持。

## 混合密钥交换怎么工作

X25519MLKEM768 在同一个 TLS 1.3 密钥份额里并排运行 ML-KEM-768 和 X25519，再把两个结果拼起来。握手消息流程不变，变的只是 `key_share` 的大小。

```text
ClientHello
  supported_groups: X25519MLKEM768, X25519, ...
  key_share (X25519MLKEM768) = ML-KEM-768 封装公钥 (1184 B) || X25519 公钥 (32 B)
                               = 1216 字节
                                   |
                                   v
ServerHello
  key_share (X25519MLKEM768) = ML-KEM-768 密文 (1088 B) || X25519 公钥 (32 B)
                               = 1120 字节

共享密钥 = ML-KEM 共享密钥 (32 B) || X25519 共享密钥 (32 B) = 64 字节
           -> TLS 1.3 HKDF 密钥派生（不变）
```

攻击者必须两个都攻破才能拿到会话密钥。ML-KEM 万一有缺陷，连接也不比传统 X25519 弱；量子计算机攻破 X25519，ML-KEM 依然有效。

代价是字节数。用 OpenSSL 3.6.1 对本地测试服务器实测：

| 配置 | ClientHello 握手消息 | ServerHello |
|---|---|---|
| 只用 X25519 | 283 字节 | 122 字节 |
| OpenSSL 默认（X25519MLKEM768 + X25519 两个份额） | 1,517 字节 | 1,210 字节 |

计算本身很便宜，ML-KEM 在普通 CPU 上很快，麻烦出在体积上。

## 截至 2026 年 11 月的支持情况

浏览器和新版服务器之间，混合 ML-KEM 已经是默认行为。

| 软件 | 状态 |
|---|---|
| Chrome | 116 版（2023 年 8 月）加入混合 Kyber（X25519Kyber768），124 版（2024 年 4 月）起桌面版默认启用；131 版改为 X25519MLKEM768，同时去掉 Kyber |
| Edge 及其他 Chromium 内核浏览器 | 跟随 Chromium 的 TLS 实现，具体取决于厂商内核版本落后多少；国内 360、QQ 浏览器等同理 |
| Firefox、Safari | 近期版本已加入 X25519MLKEM768 支持，默认是否启用因版本和平台而异，请用用户实际使用的版本测试 |
| OpenSSL | 3.5（LTS）加入 ML-KEM、ML-DSA、SLH-DSA，默认密钥份额为 X25519MLKEM768 和 X25519 |
| nginx、Apache、HAProxy | 取决于编译时链接的 TLS 库 |
| CDN | 大型国际 CDN 会和支持的浏览器协商 X25519MLKEM768；国内云厂商 CDN、负载均衡是否支持，以各自文档为准，可用下面的命令直接测 |

Chrome 131 一次只提供一个后量子密钥份额。Google 的解释是同时发送 Kyber 和 ML-KEM 会让 ClientHello 过大，所以只支持旧 Kyber 码点的服务器，和新版 Chrome 之间只能协商出传统 X25519。

服务器端通常只需要新版 TLS 库。nginx 链接 OpenSSL 3.5 或更新版本时，可以显式指定顺序：

```nginx
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1:secp384r1;
```

先用 `nginx -V` 看清链接的 OpenSSL 版本。很多发行版和宝塔默认安装的 nginx 链接的是 OpenSSL 3.0、3.2 或更早版本，它们不认识 `X25519MLKEM768` 这个名字，加上这一行 nginx 会启动失败。

命令行测试（OpenSSL 3.5+）：

```bash
openssl s_client -connect example.com:443 -servername example.com \
  -groups X25519MLKEM768 -brief </dev/null
```

```text
Connecting to 203.0.113.10
CONNECTION ESTABLISHED
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Peer certificate: CN=example.com
Signature type: ecdsa_secp256r1_sha256
Verification: OK
Negotiated TLS1.3 group: X25519MLKEM768
```

不支持的服务器会返回 `alert handshake failure`（编号 40），因为客户端没有提供别的组。注意 `Signature type: ecdsa_secp256r1_sha256` 这一行：密钥交换是后量子的，身份认证还不是。更多组和协议测试命令见[加密套件与协议命令](https://ssl.sh/zh/cookbook/ciphers-and-protocols/)。

## ClientHello 变大与中间设备

部署中最常见的问题不在密码学，而在处理不了“一个包装不下的 ClientHello”的网络设备。带 X25519MLKEM768 份额的 ClientHello 视其他扩展而定约 1.5 KB 到 1.8 KB，在常见的 1500 字节 MTU 下装不进一个 TCP 段或 QUIC 包。

已知的故障模式：

- 防火墙、TLS 解密代理、负载均衡只读第一个 TCP 段来提取 SNI，读不全就丢包或重置连接。
- 老设备为 ClientHello 分配了固定大小的缓冲区，消息超长就直接断开。
- 不认识新组的服务器只能回 HelloRetryRequest；行为规范的客户端会同时附带一个 X25519 份额来避免这多出的一次往返。

Chrome 启用混合密钥交换时，给企业管理员提供了 `PostQuantumKeyAgreementEnabled` 策略作为临时开关，等设备厂商修复。根本办法是升级中间设备；在源站启用 ML-KEM 组之前，先确认负载均衡、WAF 固件是新的。企业内网如果部署了上网行为管理或 TLS 解密设备，尤其要先测。

## 后量子证书为什么难

后量子签名比 ECDSA 大一个数量级，而一次 TLS 握手要带好几个签名。FIPS 204 及常见算法的尺寸：

| 算法 | 公钥 | 签名 |
|---|---|---|
| ECDSA P-256 | 64 字节（编码后 65） | 约 64 到 72 字节 |
| RSA-2048 | 256 字节 | 256 字节 |
| ML-DSA-44 | 1,312 字节 | 2,420 字节 |
| ML-DSA-65 | 1,952 字节 | 3,309 字节 |
| ML-DSA-87 | 2,592 字节 | 4,627 字节 |

一次典型的网站握手至少携带两个公钥（叶子证书和中间证书）和五个签名：中间 CA 对叶子证书的签名、根 CA 对中间证书的签名、服务器的 CertificateVerify，以及[证书透明度](https://ssl.sh/zh/learn/certificate-transparency/)要求的两个或更多 [SCT](https://ssl.sh/zh/glossary/sct/)。如果全部换成 ML-DSA-44，认证数据约为 5 × 2,420 + 2 × 1,312 ≈ 14.7 KB，而 ECDSA 证书链不到 1 KB。用 OpenSSL 3.6.1 在本地生成最简单的自签名证书也能看到这个跳变：P-256 为 389 字节，RSA-2048 为 785 字节，ML-DSA-44 为 3,985 字节。

14 KB 的问题在于，它会让服务器第一轮发送的数据超出 TCP 初始拥塞窗口（RFC 6928 规定的 10 个报文段），每个新连接都要多几次往返，还会加剧上一节的中间设备问题。Google 2026 年 2 月的公告明确说，Chrome 近期没有把带后量子算法的 X.509 证书加入 Chrome 根证书库的计划。

## Merkle 树证书

Merkle 树证书（Merkle Tree Certificates，MTC）用“证书包含在某棵已签名 Merkle 树中”的简短证明，取代一串签名。设计来自 IETF 的 PLANTS（PKI, Logs, And Tree Signatures）工作组，草案名为 `draft-ietf-plants-merkle-tree-certs`，由 David Benjamin 早先的个人草案发展而来。

```text
传统 X.509 + CT                              Merkle 树证书
---------------                              -------------
根 CA 签中间证书       （签名）              CA 对覆盖大量证书的树头签一次名
中间 CA 签叶子证书     （签名）              （1 个签名，浏览器提前另行获取）
CT 日志签 SCT          （2 个以上签名）
服务器签握手           （签名）
                                             服务器发送：公钥 + 包含证明（几个哈希）
服务器发送：证书链 + SCT + CertificateVerify    + CertificateVerify
```

浏览器事先拿到已签名的树头，握手里传的就只是哈希而不是大签名；而且透明度是天然的，证书不可能脱离公开的树而存在。Google 在 2026 年 2 月公布了分阶段计划：先与 Cloudflare 在真实流量上做可行性研究，期间每个 MTC 连接都有一张普通 X.509 证书兜底；然后邀请现有 CT 日志运营方启动公共 MTC；再建立只接受 MTC 的独立“Chrome 抗量子根证书库”。截至 2026 年 11 月这仍是实验，草案也还在变化。

## 防降级：认证迁移的真正难点

只增加后量子证书，在浏览器能拒绝传统证书之前保护不了任何人。拥有量子计算机的攻击者可以用任意一家受信 CA 的传统密钥伪造证书冒充网站，不管真网站用的是哪种证书。所以 Chromium 2026 年 2 月发布的后量子认证路线图分了几个阶段：先加入后量子选项；再让单个网站通过类似 HSTS 的机制选择“必须后量子”；然后要求整个 PKI 都是后量子的；最后在很远的将来要求所有服务器密钥都是后量子的。其中“网站自愿选择”的思路和 [HSTS](https://ssl.sh/zh/learn/hsts/) 一样，是一个带 `max-age`、由浏览器记住的响应头。

## 现在该做什么

大多数网站现在只需开启 X25519MLKEM768，暂时不要购买“后量子证书”。完整清单：

1. **开启混合密钥交换。** 升级到支持 X25519MLKEM768 的 TLS 库（OpenSSL 3.5+、基于新版 BoringSSL 的代理，或支持它的 CDN），用 `s_client -groups` 确认。
2. **检查网络路径。** 经过负载均衡、WAF 和 TLS 解密设备完整测一遍，大 ClientHello 最容易在这些地方出问题。
3. **保持 TLS 1.3 开启。** 混合组只为 TLS 1.3 定义，参见 [TLS 1.3](https://ssl.sh/zh/learn/tls-1-3/)。
4. **盘点长期机密。** VPN、内部 API、专线上需要保密十年以上的数据，应最先要求 ML-KEM。
5. **公网网站先别买“后量子证书”。** 把证书签发自动化，将来切换到 MTC 或 ML-DSA 时就只是改配置，而不是一个项目。

术语见[后量子密码](https://ssl.sh/zh/glossary/post-quantum-cryptography/)、[ML-KEM](https://ssl.sh/zh/glossary/ml-kem/) 和 [X25519MLKEM768](https://ssl.sh/zh/glossary/x25519mlkem768/)。
