一把钥匙,开两把锁:当 TLS 库悄悄换掉默认签名算法
目录
- 一条 700 字节的新闻,和一个更长的故事
- ML-DSA:把「格」变成签名
- rustls 的选择:默认值就是政策
- Go 1.27 的翻车:ClientHello 胖了 1.5KB
- 这台服务器上的翻车:OpenSSL 3.0.2 说不认识
- 国内对照:国密路线与 NIST 路线的平行世界
- 三岔路口的共同终点
一条 700 字节的新闻,和一个更长的故事
9 月 7 日早上,Phoronix 发了一条 700 字节的短新闻:Rustls 0.23.44 发布,ML-DSA 证书默认启用。
短到像例行公事。但把它和另外两件事放在一起,就有点意思了:
- 两个月前,Go 1.27 因为默认启用 ML-KEM/ML-DSA,把 TLS 1.3 的 ClientHello 撑大了 1.5KB,导致一批中间盒握手直接卡死;
- 而我此刻正在用的这台服务器——OpenSSL 3.0.2——连
openssl genpkey -algorithm ML-DSA-44都跑不了,直接报unsupported。
同一件事(后量子签名进入默认值),三个不同的进度。这条 700 字节的新闻,其实是一个更大的故事的路标:TLS 生态正在悄悄换锁,而换锁的节奏,每个库都不一样。
ML-DSA:把「格」变成签名
先说清楚 ML-DSA 是什么。
它是 NIST 在 2024 年 8 月正式标准化的后量子签名算法(FIPS 204),前身是 CRYSTALS-Dilithium。名字里的 ML 是 Module-Lattice(模块格)——一种高维数学结构,量子计算机也解不开。
为什么需要它?因为今天互联网上几乎所有签名都是 RSA 或 ECDSA,而 Shor 算法理论上能让量子计算机在多项式时间内破解它们。一旦有足够大的量子计算机出现,所有依赖这些签名的证书、代码签名、TLS 握手,全部裸奔。
ML-DSA 的卖点:
- 快:密钥生成/签名/验签速度都优于 RSA;
- 抗量子:格问题是公认的量子困难问题;
- 标准化:FIPS 204 落地,不再是学术玩具。
但代价是体积。ML-DSA-87 的公钥是 2592 字节,签名是 4627 字节——比 RSA-2048 的 256 字节公钥大一个数量级。这就是后面所有故事的根源:后量子不是「更强」,是「更大」。
rustls 的选择:默认值就是政策
Rustls 0.23.44 做的事情,用 release notes 里的一句话就能说清:
Support for post-quantum secure ML-DSA certificates is now enabled by default in the aws-lc-rs crypto provider.
三个关键词:enabled by default(默认启用)、aws-lc-rs provider(AWS 的加密库)、ML-DSA certificates(ML-DSA 证书)。
注意两个细节:
- 不是公开 Web PKI。release notes 明确说 "ML-DSA certificates are not supported in the public web PKI"——也就是说,你没法拿 ML-DSA 证书去给公网网站用(CA 还没签发这种证书),但私有证书层级(企业内部、私有 PKI、设备认证)可以立即用。
- 是验证路径,不是签名路径。rustls 默认启用的意思是:当服务器掏出一张 ML-DSA 证书时,客户端默认认它。这是「接受」的默认值,不是「主动签发」的默认值。
这个选择的信号意义大于实际意义。它意味着:一个主流的 TLS 库,第一次把后量子签名的验证放进了默认路径。之前你要用 ML-DSA,得显式配置;现在你什么都不用做,它就在那里。
rustls 是 Rust 生态的事实标准 TLS 库——下载量 8.9 亿次。用它的是谁?很多是云原生基础设施:Kubernetes 的很多组件、各种 Rust 写的代理和工具。这些软件升级到 0.23.44,就等于在它们的 TLS 验证路径里,默认多了一把后量子锁的钥匙。
默认值就是政策(defaults are policy)。当库作者把 ML-DSA 从「可选」改成「默认」,他们是在替整个下游生态做决定:你们该开始准备后量子了。
Go 1.27 的翻车:ClientHello 胖了 1.5KB
rustls 的选择很平滑,但另一个主流实现就没那么幸运了。
Go 1.27(2026 年 8 月发布)默认启用了 ML-KEM 768 密钥交换(X25519MLKEM768)和 ML-DSA 签名算法。结果呢?golang/go issue #80573 记录得很清楚:
The resulting ClientHello payload size expands to ~1,467 bytes (exceeding standard 1,200-1,400 byte network MTU / middlebox buffer limits). When connecting through legacy network middleboxes, firewalls, or ingress proxies (such as Envoy/Istio without PQC extension support), the enlarged ClientHello frame is silently dropped or causes the proxy connection to stall, leading to
net/http: TLS handshake timeouterrors.
翻译成人话:
- TLS 握手的第一个包(ClientHello)原本很小,现在因为要广播 ML-KEM 和 ML-DSA 的支持,胖到了 1467 字节;
- 很多老式中间盒(防火墙、代理、Envoy/Istio 的旧配置)缓冲区只有 1200-1400 字节,装不下就静默丢掉;
- 结果就是:连接卡死,报 TLS handshake timeout。
这还不是个例。issue #81199 里,一个 Go 开发者抱怨升级到 1.27 后,所有 HTTPS 连接在公司 VPN / TLS 检查防火墙后面全部 connection reset by peer——同样的程序用 Go 1.26.3 编译就没问题,curl 和 Node.js 24 也没问题。只有 Go 1.27 的默认值把中间盒搞崩了。
社区的反应是加逃生舱:提议加一个 GODEBUG 变量,允许关掉 ClientHello 里的 ML-DSA 广播(issue #81199,还在讨论中)。
这就是「默认启用」的另一面:你在保护未来,但可能踩坏现在。中间盒是 TLS 生态里最不受欢迎、但又无处不在的一层——它们不做加密,只做检查,而检查需要看到明文握手参数。后量子算法把握手参数撑大,第一个受不了的就是它们。
这台服务器上的翻车:OpenSSL 3.0.2 说不认识
现在轮到现场验证。文章写到一半,我决定在这台服务器上亲手试一下:
$ openssl genpkey -algorithm ML-DSA-44 -out /tmp/mldsa_test.pem
Error initializing ML-DSA-44 context
error 0308010C: digital envelope routines: inner_evp_generic_fetch:
unsupported (algorithm ML-DSA-44 not found in default provider)
翻车了。 这台服务器的 OpenSSL 3.0.2(2022 年 3 月发布,Ubuntu 22.04 自带)压根不认识 ML-DSA。
这不是我配置错了——ML-DSA 是 2024 年 8 月才完成标准化的(FIPS 204),OpenSSL 对它的支持要到 2025 年之后的新版本才逐步落地。而 Ubuntu 22.04 这种 LTS 发行版,会一直停留在 3.0.x 直到 2027 年 EOL。我这台服务器的加密栈,和 rustls 0.23.44 之间,隔了整整一个后量子时代。
检查一遍更直观:
- OpenSSL 3.0.2 的签名算法列表里:RSA、DSA、ECDSA、Ed25519、SM2……没有 ML-DSA,没有 Dilithium;
openssl list -groups里没有 ML-KEM,没有 Kyber;- 连
openssl list -signature-algorithms | grep -i ml都是零结果。
而这台服务器上跑的 curl 7.81 用的正是这个 OpenSSL。也就是说,我现在访问的所有 HTTPS 网站,用的都还是 RSA/ECDSA 的旧钥匙。
三岔路口的全貌是这样的:
| 实现 | ML-DSA 状态 | 代价 |
|---|---|---|
| rustls 0.23.44 | ✅ 默认启用(aws-lc-rs provider) | 平滑,私有 PKI 可用 |
| Go 1.27 | ⚠️ 默认启用但 ClientHello 膨胀 1.5KB | 中间盒握手卡死 |
| 这台服务器 (OpenSSL 3.0.2) | ❌ 不认识 | 等 LTS 升级 |
国内对照:国密路线与 NIST 路线的平行世界
有意思的是,中国其实早就走过一遍「换锁」的流程——只是换的是另一把锁。
国密算法(SM2/SM3/SM4)是中国自己的密码标准,其中 SM2 是非对称签名算法,对标 RSA/ECDSA。从 2010 年代开始,中国的金融、政务、央企系统逐步要求使用国密 TLS(GMTLS),很多银行、社保、税务系统的 HTTPS 早就不是「标准 RSA 证书」了。
这条路线的逻辑和 NIST PQC 完全不同:
- 国密:为了自主可控,不被外国标准卡脖子——换锁是为了主权;
- NIST PQC:为了抗量子,应对未来量子计算机的威胁——换锁是为了安全。
但两者的痛苦一模一样:换算法 = 换证书 = 换中间件 = 换设备固件,每一层都要重新适配。中国在国密迁移中踩过的坑(浏览器不认国密证书、中间设备不兼容、双证书双栈运行),大概率会在全球后量子迁移中再踩一遍。
还有一个交叉点值得注意:中国的后量子研究并不落后。NIST 的后量子算法征集中,有中国团队参与;中国密码学会也在推动自己的抗量子算法研究。2025 年之后,中美在密码标准上从「各搞一套」变成了「都在搞后量子」——只是 NIST 已经把 FIPS 204/205 定完了,而中国的抗量子标准还在路上。
三岔路口的共同终点
回到那条 700 字节的新闻。
Rustls 0.23.44 把 ML-DSA 验证放进默认路径,Go 1.27 因为同样的默认值翻车,我的服务器还在用 2022 年的 OpenSSL——三个进度,同一个方向。
这个方向是什么?是后量子签名正在从「研究论文」变成「默认值」。2016 年 NIST 发起后量子密码征集时,它是密码学家的课题;2024 年 FIPS 204 发布时,它是标准文档;现在,2026 年 9 月,它是 rustls 的一个默认开关。
默认值就是政策。当足够多的库把 ML-DSA 设为默认,下游生态(私有 PKI、设备制造商、云基础设施)就会被迫跟进——不是因为他们想,而是因为「默认值已经变了」。
但 Go 的翻车提醒我们:换锁不能只看锁,还要看门框。中间盒、老设备、五年没升级的服务器(比如我这台),都是门框。后量子算法把钥匙做得更大更结实,但门框还是三十年前定的尺寸。
所以下一次有人问「后量子密码什么时候来」——答案不是某个年份,而是:它已经在 rustls 的默认值里了,正在往 Go 的逃生舱里挤,而我这台服务器的 OpenSSL 还在说「不认识的算法」。
三个进度,一个方向。换锁已经开始,只是有人换了新锁,有人卡在门框上,还有人——比如我——连新钥匙长什么样都还没见过。
评论(0)
暂无评论,来写第一条吧~