跳到主要内容
ecdsa.com
← 全部文章

2026年的后量子迁移:开发团队行动计划

如今,密钥交换基本只需升级版本。签名和证书则是一个历时多年的项目,截止日期在2030年和2035年。本文说明哪些工作已经有人替你完成、哪些还没有,以及其余工作应按什么顺序进行。

简短回答:2026年,传输中加密的后量子工作有很大一部分只需升级即可完成。Chrome、Firefox、Apple 各系统的 26 版、OpenSSL 3.5、Go 1.24+、JDK 27 和 OpenSSH 10 默认协商混合 ML-KEM 密钥交换。你要做的是找出仍未做到这一点的连接:旧库、写死的组列表、中间设备、TLS 1.2、VPN、内部服务。签名和证书才是进展缓慢的部分。公共 CA 目前还不能为浏览器签发 ML-DSA 证书,所以现在就要盘点,在私有 PKI 中试点 ML-DSA,并在设计上保证算法敏捷性。规划所依据的日期来自 NIST 的草案 IR 8547:RSA-2048 等 112 位强度的密钥在2030年后弃用,所有易受量子攻击的公钥算法在2035年后禁止使用。NSA 的 CNSA 2.0 为美国国家安全系统设定了更早的日期。

两个问题,两种时间表

一旦出现具备密码破解能力的量子计算机,它就能借助 Shor 算法攻破 RSA、有限域 Diffie-Hellman 和椭圆曲线密码学(ECDH、ECDSA、EdDSA)。对称密码和哈希沿用今天的密钥长度即可保持安全,即 AES-256,以及 SHA-256 或更长的哈希。没人能告诉你这样的机器何时出现。OpenSSH 项目页面对已发表估计的概括是:“5~20 年,许多观察者预计量子计算机会在2030年代中期出现”。迁移可以拆成紧迫程度截然不同的两个问题:

  • 机密性,刻不容缓:今天被记录下来的加密流量,一旦量子计算机出现就能被解密。这就是“先收集后解密”(harvest now, decrypt later)。任何需要保密几年以上的数据,只要其密钥交换采用经典算法,现在就已经暴露。解决办法是后量子密钥交换,而且今天就可以部署。
  • 身份验证,有截止期限:伪造的签名只在有人依赖它的那一刻才会造成危害,所以那时量子计算机必须已经存在。但签名密钥和信任锚的寿命很长。根证书、固件密钥、代码签名密钥和归档的已签名文档会被信任数十年,替换它们需要好几年。

按这个顺序安排工作:先密钥交换,后签名。

真正存在的截止日期

来源状态内容
NIST IR 8547初始公开草案,2024年11月。截至2026年10月20日,csrc.nist.gov 上尚无最终版本112 位强度的 RSA、ECDSA、ECDH 和有限域 DH(RSA-2048、DH-2048、P-224):2030年后弃用。所有易受量子攻击的公钥算法,包括 P-256 和 RSA-3072:2035年后禁止使用
NSM-10(美国,2022年),IR 8547 引用政策“到2035年,在可行范围内尽可能多地缓解量子风险”
CNSA 2.0(NSA,2022年)对美国国家安全系统的要求安全类别 5 的参数(ML-KEM-1024、ML-DSA-87),固件使用 LMS 或 XMSS。Web 浏览器、服务器和云服务:到2025年支持并优先采用,到2033年全部改用。软件和固件签名:到2030年全部改用。网络设备:到2030年全部改用
欧盟协调路线图(2025年6月)对成员国的建议到2026年底启动国家计划,到2030年底完成高风险用例,到2035年底完成中风险用例
英国 NCSC(2025年3月)指南到2028年完成摸底和规划,到2031年完成最高优先级的迁移,到2035年全部完成

关于这张表,有三点需要注意:

  1. IR 8547 仍是草案:2030年和2035年这两个日期是政府机构和厂商做规划的依据,但还不是 NIST 的最终政策。在草案中,“弃用”(deprecated)表示只要你接受风险,仍然可以使用该算法;“禁止”(disallowed)表示完全不得使用。
  2. 2030年这一步针对的是 112 位强度的密钥,首当其冲的是 RSA-2048:许多证书和许多令牌签名方仍在使用 RSA-2048(下文扫描的六个端点中有两个在用)。P-256 和 RSA-3072 为 128 位强度,可以一直用到2035年,但迁移到它们最多只能多争取五年,因为草案在2035年后禁止一切易受量子攻击的算法。
  3. 对混合方案而言,CNSA 2.0 的脚注很关键:混合模式是允许的,但 CNSA 2.0 算法“将在规定日期成为必选项”,因此仅使用经典算法的配置将不再被接受。

默认已启用后量子的组件

只要两端版本足够新,下列组件无需任何配置就会协商混合 ML-KEM 密钥交换:

组件起始版本说明
ChromeChrome 131(2024年11月)X25519MLKEM768,取代了早先基于 Kyber 草案的组
FirefoxTLS 自 132(2024年10月)起,HTTP/3 自 135 起首选项 security.tls.enable_kyber,默认开启
Apple URLSession 和 Network 框架iOS、macOS 及其他系统的 26 版Apple 支持文章 122756
OpenSSL3.5.0(2025年4月),当前的 LTS 版本,支持到2030年4月8日默认密钥共享(key share)为 X25519MLKEM768 和 X25519
Go crypto/tls1.24(2025年2月)Config.CurvePreferences 为 nil 时
Java JSSEJDK 27(2026年9月),JEP 527X25519MLKEM768 位于默认列表首位
OpenSSH9.0(sntrup761 混合方案),10.0(默认 mlkem768x25519-sha256)10.1+ 会在会话未采用后量子算法时发出警告

服务端也在跟进。2026年10月20日,用 OpenSSL 3.5.7 运行盘点一节中的脚本扫描,结果如下:

inventory.sh,2026年10月20日(OpenSSL 3.5.7)
www.cloudflare.com:443     TLSv1.3  X25519MLKEM768    id-ecPublicKey 256 bit    ecdsa-with-SHA256
github.com:443             TLSv1.3  X25519,253bits    id-ecPublicKey 256 bit    ecdsa-with-SHA256
www.google.com:443         TLSv1.3  X25519MLKEM768    id-ecPublicKey 256 bit    ecdsa-with-SHA256
login.microsoftonline.com:443 TLSv1.3  ECDH,secp384r1    rsaEncryption 2048 bit    sha256WithRSAEncryption
api.stripe.com:443         TLSv1.3  X25519,253bits    rsaEncryption 2048 bit    sha256WithRSAEncryption
letsencrypt.org:443        TLSv1.3  X25519,253bits    id-ecPublicKey 256 bit    ecdsa-with-SHA384

有两列最能说明问题。密钥交换参差不齐:有些服务已经用上混合方案,有些还没有。证书相关的列则清一色是经典算法:ECDSA P-256 或 RSA-2048。SSH 也是如此,GitHub 已经会为 OpenSSH 10 客户端选择混合方案:

ssh -v git@github.com(OpenSSH 10.0p2,2026年10月20日,节选)
debug1: kex: algorithm: mlkem768x25519-sha256

第 1 步:盘点

列不出来的东西,就无从迁移。一份有用的密码资产清单,要针对每一处公钥密码的使用回答这些问题:用的是什么算法和密钥长度,哪个库、哪个版本,谁掌控配置,受保护的数据需要保密多久,以及密钥或签名需要被信任多久。

先从能在外部测量的部分入手,也就是你的 TLS 端点:

inventory.sh:逐个端点检查密钥交换和证书(OpenSSL 3.5)
#!/bin/bash
for target in "$@"; do
  host=${target%:*}; port=${target##*:}; [ "$host" = "$target" ] && port=443
  out=$(openssl s_client -connect "$host:$port" -servername "$host" -brief </dev/null 2>&1)
  proto=$(grep -m1 "^Protocol version" <<<"$out" | cut -d: -f2 | xargs)
  group=$(grep -m1 "^Negotiated TLS1.3 group" <<<"$out" | cut -d: -f2 | xargs)
  [ -z "$group" ] && group=$(grep -m1 "^Peer Temp Key" <<<"$out" | cut -d: -f2 | cut -d, -f1-2 | tr -d ' ')
  cert=$(openssl s_client -connect "$host:$port" -servername "$host" </dev/null 2>/dev/null | openssl x509 -noout -text 2>/dev/null)
  key=$(grep -m1 "Public Key Algorithm" <<<"$cert" | cut -d: -f2 | xargs)
  bits=$(grep -m1 -o -E "\([0-9]+ bit\)" <<<"$cert" | tr -d '()')
  sig=$(grep -m1 "Signature Algorithm" <<<"$cert" | cut -d: -f2 | xargs)
  printf '%-26s %-8s %-17s %-25s %s\n' "$host:$port" "$proto" "$group" "$key $bits" "$sig"
done

脚本必须用 OpenSSL 3.5 客户端运行:旧版客户端从不提供混合方案,在它们看来每台服务器都只支持经典算法。如需一次检查多个域名,批量域名检测会逐台主机报告密钥交换、证书算法和到期时间。

然后转向内部,大部分工作都在这里:

  • 库和运行时:列出每个镜像和每台主机上的 OpenSSL、BoringSSL、Go、JDK、.NET、Node.js 和 Python 版本。OpenSSL 3.0 已不再获得上游支持,也没有 ML-KEM,而 Ubuntu 24.04 仍然搭载它。仅这一点就能解释很多扫描结果。
  • 显式配置:搜索 ssl_ecdh_curve、SSLOpenSSLConfCmd Groups、CurvePreferences、jdk.tls.namedGroups 和 KexAlgorithms 这类组列表和加密算法列表。每一处都是升级带来的新默认值管不到的地方。
  • 代码:搜索直接调用 RSA、ECDSA、ECDH 和 Ed25519 API 的地方、密钥长度、JWT 的 alg 值,以及数据库中存储的公钥。存储在数据格式中的签名,日后最难更改。
  • 长期有效的密钥和证书:私有 CA 的根证书、代码签名和固件密钥、文档签名、SSH CA、保存在 HSM 中的密钥。记下每一项的到期日,以及 HSM 支持的算法。
  • 供应商:负载均衡器、WAF、做 TLS 检查的代理、VPN 集中器、托管数据库、SaaS API。要求每家供应商以书面形式提供 ML-KEM 和 ML-DSA 路线图。

把结果记录成机器可读的格式。CycloneDX 正是为此新增了密码物料清单(CBOM)。它把算法、密钥、证书和协议描述为软件清单中的组件,与你可能已经在生成的软件包 SBOM 放在一起。

第 2 步:完成密钥交换迁移

对你能控制的每个 TLS 终止点:

  1. 升级 TLS 库:OpenSSL 3.5、Go 1.24 或更高版本、JDK 27,或较新的 BoringSSL 或 AWS-LC 构建。
  2. 删除写死的组列表,或者把 X25519MLKEM768 放在列表首位。从旧指南里复制来的一行加固配置,是现代服务器只协商出普通 X25519 的最常见原因。具体机制见 X25519MLKEM768 详解。
  3. 通过真实的网络路径测试:混合 ClientHello 约为 1.5 KB。某些防火墙、负载均衡器和 TLS 检查代理遇到跨两个数据包的 ClientHello 就会出错。在归咎于服务器之前,先通过同一路径对比一次混合握手和一次纯经典握手。
  4. 两段都要检查:在 CDN 或负载均衡器之后,边缘到源站的连接是一个独立的 TLS 会话。这一段上被记录的流量同样可能被收集,留待日后解密。
  5. 尽可能淘汰 TLS 1.2:混合组只为 TLS 1.3 定义。

接下来是 Web 以外的通道:

  • SSH:只要两端都支持,OpenSSH 9.0 及更高版本已经会协商后量子混合方案。旧服务器、网络设备和嵌入式 SSH 协议栈往往不支持。OpenSSH 10.1 及更高版本的客户端会打印一条点明风险的警告:“This session may be vulnerable to 'store now, decrypt later' attacks.”
  • VPN 和 IPsec:IKEv2 支持附加密钥交换(RFC 9370),厂商借此加入 ML-KEM。查看网关固件的版本说明。
  • 应用层加密:凡是用 RSA 或 ECDH 包装数据密钥的场景,例如信封加密、加密备份或端到端消息,都需要一条 ML-KEM 或混合 KEM 的路径。搭配混合 KEM 的 HPKE(RFC 9180)是常用的基础组件。HPKE 演练场展示了各个部分如何组合在一起。

第 3 步:签名与证书

在这方面,生态系统还没准备好替你完成,所以2026年的工作是做准备:

  • 公共 Web 证书:等待,但要做好准备:没有任何浏览器接受公共 CA 签发的 ML-DSA 证书。Chrome 在2026年2月表示,近期没有把带后量子密钥的 X.509 证书加入其根证书库的计划。它正在围绕 Merkle 树证书(Merkle Tree Certificates)构建一个独立的抗量子根证书库,相关标准正在 IETF PLANTS 工作组中制定。在此之前,有价值的工作是自动化。能在几分钟内轮换任意证书的团队,切换算法也会很轻松,而更短的证书有效期也在朝同一个方向推动。
  • 私有 PKI:现在就试点 ML-DSA:内部 mTLS、服务网格、设备身份和 VPN 证书的两端都在你的掌控之中。OpenSSL 3.5、Go 1.27、Java 24+、.NET 10 和 BouncyCastle 都能处理 ML-DSA 密钥和证书。使用 ML-DSA-65 时,叶子证书预计约 5.5 KB;测试哪些环节会因此出问题:缓冲区大小、头部大小限制、HSM 支持。面向开发者的 ML-DSA 提供了可运行的代码,并介绍了密钥格式方面的陷阱。
  • 长期信任锚优先:2026年创建的根密钥或固件密钥,在2035年之后仍会被信任。对于固件和软件更新签名,CNSA 2.0 要求使用有状态的基于哈希的方案 LMS 或 XMSS(SP 800-208),并期望到2030年全部改用。无法管理签名状态时,无状态的 SLH-DSA(FIPS 205)是保守的替代方案。
  • 必须保持可验证的已签名制品:今天用 ECDSA 签名的文档、归档和日志,必须在其签名不再可信之前重新加以保护。规划时间戳续期和归档重新签名,就像 PDF 长期验证已经针对即将过期的证书所做的那样。
  • 令牌与 API:JOSE 和 COSE 已为 ML-DSA 分配了代码点(RFC 9964)。3.3 KB 的签名会让 JWT 在 base64url 编码后达到约 4.5 KB,这对 Cookie 和请求头有影响。切换之前先测量。

第 4 步:让下一次变更代价更低

迁移不会一次切换就完成。混合密钥交换以后可能让位于纯 ML-KEM。FN-DSA 可能会加入 ML-DSA 的行列,NIST 计划将其发布为 FIPS 206。复合签名和混合签名仍在设计之中。密码敏捷性能让其中每一次变更都不至于又变成一个历时多年的项目:

  • 算法标识符随数据一起传递(OID、JOSE 的 alg、版本字节),验证方据此选择处理方式,而不是自行假定。
  • 密钥长度和签名大小没有写死。数据库列、缓冲区和协议字段都留有容纳数 KB 数据的空间。
  • 密钥由自动化流程生成、存储和轮换。没有人手动把 PEM 文件复制进配置。
  • 每个技术栈的配置都集中在一处,下一次更换组或算法只需改一个地方。

常见错误

  • 用旧客户端测试:OpenSSL 3.0 的 openssl s_client,或链接到它的 curl,从不提供混合方案。这样一来,每台服务器看起来都只支持经典算法,包括已经完成迁移的服务器。
  • 把 CDN 边缘当成整条连接:浏览器到边缘的一段往往已是后量子的,而同一请求中边缘到源站的一段却不是。
  • 为解决中间设备故障而禁用混合方案:这会让所有连接失去保护。应该修复或更换该设备。
  • 等公共 ML-DSA 证书出来再动手:盘点、库升级和证书自动化无论如何都要做,而且它们花的时间比等待还长。
  • 把“2030年后弃用”理解为“2035年前都允许”:2029年用经典密钥交换加密的数据,在需要保持机密性的整个期限内都处于暴露状态。这些截止日期针对的是合规,而不是安全。

2026年剩余时间的检查清单

  1. 用 OpenSSL 3.5 扫描每个公开和内部 TLS 端点,记录组、证书算法和库版本。
  2. 升级基础镜像中的 TLS 库。删除写死的组列表。重新扫描。
  3. 测试混合方案能否穿过路径上的每台中间设备,包括边缘到源站这一段。
  4. 将 SSH 服务器升级到 OpenSSH 9.9 或更高版本以获得 ML-KEM(9.0 及更高版本已提供 sntrup761 混合方案);有可用固件的网络设备也要升级。
  5. 列出每个长期使用的签名密钥和信任锚,注明其到期时间和所在 HSM 支持的算法。
  6. 搭建一个 ML-DSA 测试 CA,并为一个内部服务签发证书。
  7. 在所有仍靠手工操作的地方,实现证书签发和轮换的自动化。
  8. 以书面形式向供应商索取 ML-KEM 和 ML-DSA 的支持日期。

参考资料

扫描于2026年10月20日在 node:24.22.0-trixie(OpenSSL 3.5.7、OpenSSH 10.0p2)中运行。