Skip to content

필사 모드: 后量子证书为何还没到来 — ML-DSA 签名大小、10kB 之墙,与 Merkle Tree Certificates

中文
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

引言 — 加密已经过半,认证仍在起跑线上

过去几年里,后量子密码(PQC)的叙事实际上一直是密钥交换的叙事。逻辑很简单 — 把眼下往来的密文原样存起来,日后用量子计算机破解,也就是所谓的harvest now, decrypt later(HNDL)攻击是可行的,所以加密必须现在就换掉。于是混合密钥交换X25519MLKEM768很快就铺到了浏览器和服务器上。Cloudflare 表示,截至 2025 年 10 月,进入其边缘网络的流量中约有 50% 已受到这一威胁的防护(厂商自测 — 统计对象是到达 Cloudflare 边缘的流量,而非整个互联网)。

认证(authentication)则是另一回事。伪造签名不是可以存起来留到以后做的事,而必须在连接存活的那一刻完成。所以签名不是 HNDL 的目标,其威胁取决于是否真的存在密码学意义上的量子计算机(CRQC)。借用 Let's Encrypt 的说法,这个事实一直是让认证这一侧可以往后拖的「安慰」。

但真正的原因在别处。直接把 PQ 证书换上去,Web 会变慢。而且是为了防范一个尚未到来的威胁,付出的却是眼下立刻变慢的代价。本文从一手资料核实这笔权衡背后的数字,再看看业界为躲开这笔代价选择了怎样的迂回路线。

问题全在大小 — FIPS 204 定下的数字

先把数字钉死。NIST FIPS 204 的 Table 2 以字节为单位,规定了 ML-DSA 的密钥和签名大小。

参数集            私钥      公钥      签名        (FIPS 204 Table 2)
ML-DSA-44        2560     1312     2420        安全强度类别 2
ML-DSA-65        4032     1952     3309        安全强度类别 3
ML-DSA-87        4896     2592     4627        安全强度类别 5

比较对象是这样的。当今 Web 上最常见的签名 ECDSA P-256,签名 64 字节,公钥 64 字节。RSA-2048 签名 256 字节,公钥 256 字节。Ed25519 是密钥 32 字节、签名 64 字节(RFC 8032,MTC 草案引用的数值)。

也就是说 ML-DSA-44 大约是 ECDSA P-256 的 20 倍。Cloudflare 把它形容为「roughly a 20-fold increase in size」。这里要注意的是,ML-DSA-44 已经是最小的选项。作为参照,基于哈希的 SLH-DSA(FIPS 205,旧称 SPHINCS+)按 Cloudflare 的测量会多加 39kB,签名与验证的计算成本也更高。它的优势在于只依赖哈希,安全性因此被理解得远为透彻 — 这是大小与信任度之间的取舍。

为什么握手要携带 5 个签名

单看大小是 20 倍,还拼不出全貌。关键在于握手到底携带了多少个签名。Cloudflare 的Merkle Tree Certificates 介绍文章(2025 年 10 月 28 日,Luke Valenta、Christopher Patton、Vânia Gonçalves、Bas Westerbaan)把这级台阶一步步搭了出来。

  1. 如果客户端已经知道服务器的公钥,1 个签名就够了。可是 Web 上大约有 10 亿台 TLS 服务器,密钥还在不断变化。给每个客户端预先塞进每台服务器的公钥是不可能的。PKI 设计的起点正是这个可扩展性问题。
  2. 于是证书登场。CA 签名证明「这个公钥属于这个域名」。签名 +1,公钥 +1 → 合计签名 2 个,公钥 1 个。
  3. 如今的证书链通常有 2 张以上。CA 也得轮换密钥,而新公钥传播到数十亿客户端的信任存储里需要时间。为了填补这段空档,就用旧密钥为新密钥签发一张证书,接在链的末端。签名 +1,公钥 +1 → 签名 3 个,公钥 2 个。
  4. 最后是 Certificate Transparency。Chrome、Safari、Firefox 只接受被记录进至少 2 个受信任日志的证书。每个日志各附带一个 SCT 签名。签名 +2 → 最终合计签名 5 个,公钥 2 个。

Cloudflare 的说法精准概括了这个局面 — WebPKI 每次要修补点什么,就再叠加一个签名,而传统密码学足够便宜,这套策略才行得通。如今这笔账单要偿还了。

把 FIPS 204 的大小乘以 Cloudflare 数出的个数,结果如下(以下是结合两份一手资料得出的笔者本人的算术,并非任何一方发布的实测值)。

若全部换成 ML-DSA-44 的认证数据:
  5 个签名 x 2,420 =  12,100 字节
  2 个公钥 x 1,312 =  2,624 字节
  ------------------------------------
  合计                14,724 字节

同样个数换成 ECDSA P-256 计算:
  5 个签名 x 64 + 2 个公钥 x 64 = 448 字节
(实际证书链会混入 RSA,因此实战数值会比这更大)

MTC 草案本身也给出了更保守的算法。即便用draft-ietf-tls-trust-anchor-ids让客户端直接信任中间证书从而缩短链条,草案也写明仅 2 个 SCT 加 1 个叶证书签名,在 ML-DSA-44 下就要多出 7,260 字节的认证开销,在 ML-DSA-65 下是 9,927 字节。也就是说,即便把链条削到极限,也仍然在一万字节上下。

10kB 之墙 — Cloudflare 2021 年的实测

那么一万多字节为什么是个问题?从这里开始就不再是理论,而是测量了。Cloudflare 于 2021 年 11 月 8 日公开的Sizing Up Post-Quantum Signatures(Bas Westerbaan)是一次大规模实验,在真实互联网上,为进入其网络的连接附加虚拟证书,测量大小带来的影响。这是厂商自测,统计对象是到达 Cloudflare 网络的真实客户端连接。

需要先解释一个背景概念。TCP 为了避免拥塞,一开始只发送少量数据包 — 通常是 10 个,约 14kB。这就是初始拥塞窗口(initcwnd)。一旦超过这个门槛,就会多产生一次往返。

测量结果有两条(以下依据 Cloudflare 自己在后续文章中的总结)。

  • 失败: 在现有证书链上多加超过 10kB,客户端与中间盒(middlebox)的失败率会陡然上升。图表在 10kB 和 30kB 处出现骤升区间,意味着存在扛不住这个大小的客户端或中间盒。
  • 延迟: 加不到 9kB 时,TLS 握手时间会慢约 15%。Cloudflare 给出的评价是「扛得住,但并不理想」。

这里要指出一个常被误解的地方。Cloudflare 自己的 initcwnd 并非标准值 10,而是 30 个数据包。所以即便多加 35kB,也仍落在初始拥塞窗口以内。可即便如此,中位数握手仍慢了 40%,最慢的那 10% 更是多花了 60% 的时间。Cloudflare 的结论是 — 落在拥塞窗口以内,绝不意味着多出来的数据就是免费的。

还有一个具体的代入案例。若直接替换成 Dilithium2(ML-DSA-44 的前身),会多加约 17kB,在 Cloudflare 的 30 包窗口下,中位数下降了 20%。文章还写道,在标准 initcwnd 为 10 的情况下预计会下降 60%~80% — 这是 Cloudflare 的估算,而非实测。

浏览器一侧的基准线也值得参考。Chrome 把 TLS 握手时间的退化上限定在 10%,并报告说在推出 PQ 密钥协商时已经经历了 4% 的下降 — 代价是服务器到客户端多了 1.1kB,客户端到服务器多了 1.2kB。Cloudflare 指出这个比例在比例意义上比自己「9kB 对应 15%」的数字更大,并解读为可能是因为上传比下载更慢。

Cloudflare 在 2021 年得出的实务结论可以浓缩成一句话 — 如果 6 个签名和 2 个公钥能压进 9kB 以内,迁移会最容易。而前面算出的 14,724 字节,远远超出了这个目标。

要诚实地补充一点,这次测量是 2021 年的数据。中间盒和客户端在这期间都可能发生了变化,而 Cloudflare 自己在后续文章里虽然持续引用这份数据,却也没有再给出经过更新的大规模实测。

Merkle Tree Certificates — 干脆把签名去掉的设计

数字变成这样,选项就剩三个:(1) 接受变慢这件事,(2) 拖到 Q-day 临近再说,(3) 把握手实际携带的签名数量本身降下来。

(2) 很危险。迁移总是比预期花更久,用 Cloudflare 的话说是「玩火」。业界选择的是 (3)。

核心思路是这样的:不要给每张证书单独签名,而是打成一批,只对一棵树的树头(tree head)签一次名。每张证书成为这棵树的一个叶子,内部节点则是子节点的哈希。这样,发给浏览器的「证书」就不再是沉重的签名链,而是一份证明自己身处这棵树中的轻量包含证明(inclusion proof)。照搬 Google 的说法:CA 只对代表数百万张证书的一个树头签一次名,而发给浏览器的证书,不过是针对这棵树的一份轻量包含证明。

术语最好遵循draft-ietf-plants-merkle-tree-certs-05(2026 年 7 月 6 日,100 页 — David Benjamin/Google、Devon O'Brien/Apple、Bas Westerbaan 与 Luke Valenta/Cloudflare、Filippo Valsorda/Geomys)给出的定义。

  • Cosignature: CA 或其他 cosigner 对某个检查点(checkpoint)或子树所做的签名。
  • Landmark: 为了把可信子树预先分发给 relying party,而选取的一组稀疏的树大小集合。
  • Standalone certificate: 对某个子树的包含证明,加上针对该子树的若干 cosignature。
  • Landmark-relative certificate: 只带有对某个 landmark 子树的包含证明、完全不含任何签名的优化版证书。

最后一项正是这个设计的核心。只要客户端已经预先知道 landmark,服务器就完全不需要发送签名。

还有一个额外收获。Certificate Transparency 被内置进了设计本身。今天的 CT 是事后打的补丁 — CA 先签发,再单独记入日志,然后把见证这件事的 SCT 签名塞进握手里。而在 MTC 中,证书根本无法存在于 Merkle 树之外。用 Google 的说法,不把证书放进公开树里就发行证书是不可能的。于是今天 CT 带来的安全属性成了默认自带,而堆在握手上的 SCT 开销就此消失。

草案还提到了日志运营成本这一侧的好处。由于日志条目用哈希取代了公钥、且不携带签名,日志条目大小不再随公钥、签名的大小成比例增长。而且早已过期的条目可以被剪枝(pruning),日志大小因此由保留策略决定,而不是由日志的存续时间决定。这一点,恰好和证书有效期变短的趋势相吻合。

736 字节这个数字背后的条件

介绍 MTC 的文章喜欢引用的数字是 736 字节。这个数字的出处不是 Google 或 Cloudflare 的博客,而是草案第 6.5 节 Size Estimates,并且附带了一套密密麻麻的条件。抛开条件单独引用,就会造成误解。

草案明确列出的假设是这样的。

  • 日志所用的哈希函数是 SHA-256。
  • 截至 2025 年 6 月 9 日的公开统计:单单 Let's Encrypt 一家 CA 的有效证书就约有 5.58 亿张,按 MerkleTown 统计,CT 日志中未过期证书总数约 21 亿张,全部 CA 的整体签发速率约为每小时 44.4 万张。
  • 假设 Web 已转向短生命周期证书:证书有效期 7 天,订阅者在有效期的 75% 处续期 → 每 126 小时重新签发一次 → 每家 CA 每小时约 440 万张,整体约 1,700 万张。

在这些假设之上,得出下面的计算。

若每小时分配一个 landmark:
  子树包含约 4,400,000 张
  -> 包含证明需要 23 个哈希
  -> 736 字节,无签名

standalone 证书(每 2 秒打一次检查点):
  子树包含约 2,500 张
  -> 包含证明需要 12 个哈希 = 384 字节
  -> 还要在此基础上额外附加足以满足 relying party 要求的签名

证明大小是对数级的:
  32 个哈希 = 1024 字节即可覆盖到 2^32(约 43 亿)张

草案自己给出的一个对比很有冲击力 — 736 字节比单单一个 ML-DSA-44 签名(2,420 字节)还要小,比包含一个 PQ SCT 所需的 3 个 ML-DSA-44 签名(7,260 字节)几乎小了 10 倍。Let's Encrypt「即便用上后量子算法,也能比今天的握手更小」这一说法,正是由此而来。

不过有一点必须强调。这是建立在明确假设之上的估算,而不是实测。草案自己也写明,当前 Web PKI 的签发速率未必能代表转向短生命周期证书之后的 Web。而且 736 字节只适用于 landmark-relative 证书,也就是说只适用于保持最新状态的客户端。用草案摘要自己的话说,这项优化的代价是「只适用于保持最新状态的 relying party,其余的则要用更旧的证书」。

现在走到了哪一步 — PLANTS、Chrome、Let's Encrypt

这套设计不是纸上谈兵,证据是时间表和代码。

IETF。PLANTS 工作组(PKI, Logs, And Tree Signatures)已经成立并在运作。其章程写明的目标很清楚 — 在使用 CT(RFC 6962、RFC 9162)的 PKI 中,降低大尺寸后量子签名在 TLS(RFC 8446)这类交互式协议里的成本。章程称大小是主要动机,但也表示成果应当能用于传统签名。WG 草案已经推进到了前面看到的-05(2026 年 7 月 6 日)。

Chrome。Google 在 2026 年 2 月的Cultivating a robust and efficient quantum-safe HTTPS一文中定下了方针 — 为了生态系统的可扩展性与效率,目前没有把携带 PQC 的传统 X.509 证书加入 Chrome Root Store 的即时计划。取而代之的是推动 MTC,并把上线路线分成三个阶段。

  • 第一阶段(进行中): 与 Cloudflare 合作的可行性研究。在这项实验中,每一个基于 MTC 的连接都由传统的、受信任的 X.509 证书兜底。Google 称之为「fail safe」,用意是在不拿用户连接的安全性或稳定性冒险的前提下,测量真实的性能收益和签发可靠性。
  • 第二阶段(目标 2027 年第一季度): 邀请那些在 2026 年 2 月 1 日之前,就在 Chrome 中运营过至少一个「可用(usable)」日志的 CT 日志运营方,来一起搭建公开的 MTC 基础设施。这一阶段初期,会敲定一个新的信任存储 CQRS(Chrome Quantum-resistant Root Store),以及仅支持 MTC 的 root program 的要求。它会与现有的 Chrome Root Program 并行运营,站点可以自行选择(opt-in)启用降级保护。
  • 第三阶段(目标 2027 年第三季度): 把更多 CA 接入 CQRS。

Google 补充说,对于私有 PKI(不进入 Chrome Root Store 的 PKI),预计今年内就会支持使用量子抗性算法的「传统」X.509。这意味着公开 Web 与私有 PKI 的路径会分道扬镳。

Cloudflare。这次实验的设计很巧妙。要成为一家正经的 CA,赢得浏览器信任得花上好几年,所以 Cloudflare 在这次实验中并不真的成为 CA,而是模拟(mock)MTCA 这个角色。它在 Workers 之上、基于 StaticCT 日志运行 MTCA,但每签发一个 MTC,都会同时公开一张由受信任 CA 签发的既有证书,这被称为 bootstrap certificate。当 Chrome 的基础设施拉取 MTCA 日志时,也会一并取得这张 bootstrap 证书,核对两者是否一致,只有一致时才会把 landmark 推送给 Chrome 客户端。说到底,Cloudflare 只是把(已经由受信任 CA 完成域名验证的)既有证书「重新编码」成 MTC,而 Chrome 则用 CT 来牵制 Cloudflare。这是一种在完全不改变信任关系的前提下试验设计的方法。对象是有足够流量可供测量的一部分免费客户,上线速度由 Chrome 掌控。

Let's Encrypt。2026 年 6 月 3 日,Andrew Gabbitas 撰写的A Post-Quantum Future for Let's Encrypt宣布将 MTC 定为自己的路线。目标是 2026 年底建成签发 MTC 的预发布(staging)环境,2027 年具备生产就绪环境。Let's Encrypt 明确表示这不是件小事 — 签发基础设施、订阅者使用的 ACME 协议、吊销与运维工具,以及被 MTC 吸收掉的透明度日志基础设施,整条技术栈都得跟着变。它拿出来做依托的资产,是自 2019 年起运营的 CT 日志 — 那个日志本身就是一棵 append-only 的 Merkle 树,和 MTC 是同一种数据结构。

周边标准与实现。在 X.509 中使用 ML-DSA 的约定已经以RFC 9881(2025 年 10 月,Standards Track)的形式发布,TLS 1.3 一侧的draft-ietf-tls-mldsa(截至 2026 年 7 月 8 日为-05)仍在推进中。语言运行时也跟了上来 — Go 新增了crypto/mldsa包,实现 FIPS 204 的 ML-DSA,crypto/x509支持 ML-DSA 的密钥与签名,crypto/tls在 TLS 1.3 中支持MLDSA44/MLDSA65/MLDSA87这几种 SignatureScheme。不过这以 Go 1.27 的发行说明为准,而 1.27 尚未发布(目前的稳定版是 1.26.x)。Let's Encrypt 把这一点视为「后量子签名正在成为实用基础设施的信号」。

对这套方案的反对意见与尚存的缺口

读到这里,MTC 看起来像是一场干净利落的胜利。老实地把另一面也看一看。有意思的是,下面这些反对意见里有不少正是 Cloudflare 自己写在自家文章里的。

有一种质疑认为「执着于握手时间」这个框架本身就有问题。依据有两条。第一,用上会话恢复(session resumption)之后,不必每次连接都重发证书。第二,一次典型网站访问所传输的数据量,远远压过 PQ 证书多加的那几 kB。Cloudflare 直接引用的例子,是 2024 年亚马逊研究者的一篇仿真论文,其论点是典型连接会发出多次请求、传输数百 kB 数据,因此握手上的性能下降会被淹没在误差范围内。作为参照,Cloudflare 自己也写过,TLS 握手不过是页面呈现之前那条长链条中的一个环节,大约只占其中的 5%~20%。

MTC 的收益只有在客户端保持最新时才会出现。Cloudflare 这次实验想得到答案的问题,恰恰就是这个 — 「究竟会有多少客户端能一直保持最新?」 MTC 的有效期预计在一周左右,如果客户端手里最新的 landmark 比这还旧,服务器就得回退(fallback)到更大的证书。这种回退发生的频率有多高,是调校协议参数的核心,而目前还没有答案。736 字节这个乐观数字和 standalone 回退之间的真实比例,要等这次实验结束才会揭晓。

新的信任存储不是免费的。CQRS 是与现有 Chrome Root Store 分开、只支持 MTC 的 root program。技术上很干净,但这同时也意味着把生态系统一分为二,并要求 CA 走一条新的接入路径。Google 自己把这称为「risk-managed transition」,并表示会让两条轨道并行运营,这本身也说明了运维负担有多大。

所有的时间表都是预测。而这些预测的根基 — Q-day — 没有人知道。这里尤其需要小心。Let's Encrypt 写道「今年以来时间表提前了」,并称 Google 收窄了 CRQC 到来的估计,是它宣布要在 2029 年前完成自身服务迁移的依据,Cloudflare 也随之跟进。这是那些公司的预测与宣告,而不是量子计算机会在 2029 年到来这个事实。

监管层面的时间表同样是草案。常被引用的 NIST 迁移指南IR 8547,是 2024 年 11 月 12 日公开的初期公开草案(Initial Public Draft),意见征集已于 2025 年 1 月 10 日截止。内容也比常见的概括更有层次。草案的表格按安全强度划分签名算法族:112 位强度(如 RSA-2048)标注为 2030 年后 deprecated、2035 年后 disallowed,128 位及以上标注为 2035 年后 disallowed。也就是说,「RSA 和 ECC 到 2030 年就全部死掉」这类概括,比草案表格本身粗糙得多。而且正如 Let's Encrypt 指出的,这类指南并不直接约束公开 Web PKI — 只是会促使 Web PKI 所依赖的厂商、库和标准组织跟着这条时间线走。NSA 的 CNSA 2.0 自 2022 年起就为国家安全系统给出了 2030~2035 年的时间表,欧盟的路线图则以 2030 年底前完成高风险系统迁移、2035 年完成广泛迁移为目标。

那么现在到底该做什么

本文的实务结论略显平淡。服务器运营者现在该动手的是密钥交换,而不是证书。

Let's Encrypt 在文章末尾留下的建议正是如此。对更广泛的互联网社区而言,更紧迫的问题是后量子加密,因为没有 PQ 密钥交换的 TLS 连接,现在就可能被采集起来,留到以后再解密。如果你在运营服务器,请确保它支持混合 PQ 密钥交换(X25519MLKEM768)。主流浏览器和操作系统已经支持,而在服务器端打开它,用他们的话说,是今年能做的杠杆效应最大的一件事。

证书这一侧的标准还没定型,所以现在能做的事情有三件。

  • 跟进。如果你维护着 ACME 客户端,或者运营着基于 ACME 的证书流水线,现在是关注 PLANTS 工作组和mtcs@chromium.org邮件列表的时候了。Let's Encrypt 直接给出了这条建议 — 即将到来的一些变更需要客户端侧的支持,只有签发一侧准备好的同时客户端也准备好了,生态系统才能运转起来。
  • 盘点与密码敏捷性。如果不知道哪里在用哪种签名,任何时间表都没有意义。公开 Web PKI 与私有 PKI 会走上不同的路径 — 私有 PKI 可以先转向使用 PQC 的传统 X.509,Chrome 也表示会支持这种用途。
  • 接受眼下什么都不会变这个事实。用 Let's Encrypt 的话说,今天不会有任何变化。现有证书照旧签发、照旧续期。

这不意味着不需要抓紧。而是说,该抓紧的地方不是证书。

结语

归纳一下。在后量子迁移中,加密已经走完了大约一半,认证之所以卡住,不是因为密码学,而是因为大小。把 FIPS 204 规定的 ML-DSA-44 签名 2,420 字节,乘上今天握手所携带的 5 个签名、2 个公钥,得到的是一万四千多字节,远远超出了 Cloudflare 在 2021 年实测出的那堵墙 — 超过 10kB 失败率就会飙升,即便不到 9kB 也会慢 15%。

Merkle Tree Certificates 靠的不是新算法,而是结构来解决这个问题 — 把证书打成一批,只对一个树头签一次名,握手上只携带包含证明,并把 CT 内置进签发流程,让 SCT 签名的开销就此消失。按草案的估算,对保持最新的客户端而言,这只需要 736 字节、零签名。转向后量子反而比今天更小这个说法,正是由此而来。

但这附带着条件。那个数字是建立在 7 天有效期、每小时一个 landmark 这类假设之上的估算,只有客户端持有最新 landmark 时才成立,否则就会回退到更大的证书。回退发生得有多频繁,正是 Chrome 和 Cloudflare 眼下用真实流量在测量的问题,在答案出来之前,736 字节是一个目标值,而不是实测值。标准还停在-05草案,Let's Encrypt 的生产环境目标是 2027 年,Chrome 的新根存储计划在 2027 年第三季度。这一切,都还只是计划。

作为工程师,从这里能带走的教训有点普适性。WebPKI 过去 20 年里每次要修补点什么就叠加一个签名,之所以行得通,是因为传统密码学足够便宜;而这份积累下来的便利,在算法一下子变大 20 倍的那一刻,就变成了账单。大小变成 20 倍,唯一的出路就是把数量削减到二十分之一。MTC 做的,正是这件事。

参考资料

현재 단락 (1/103)

过去几年里,后量子密码(PQC)的叙事实际上一直是密钥交换的叙事。逻辑很简单 — 把眼下往来的密文原样存起来,日后用量子计算机破解,也就是所谓的harvest now, decrypt later(H...

작성 글자: 0원문 글자: 11,667작성 단락: 0/103