首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >PQC 迁移的可观测性:怎么确认线上真的走了混合路径

PQC 迁移的可观测性:怎么确认线上真的走了混合路径

原创
作者头像
用户12439200
修改2026-09-11 13:05:13
修改2026-09-11 13:05:13
980
举报

关于 FIBEMATE:FIBEMATE 是一个开源的后量子密码(PQC)工程验证平台,覆盖算法元数据注册表、CBOM 盘点、CI 策略门禁、KAT 自测与硬件加速基准五条流水线。本篇的数据与工具全部来自主仓库 github.com/Lennonhaha/fibemate 的 tools/deploy/docs/pqc-readiness.md,均已在生产服务器上实测运行。官网:fibemate.net


1. 配置上线了,不等于混合密钥交换在跑

多数团队的 PQC 验收止步于一句“配置已上线”。问题在于混合密钥交换横跨三个彼此独立的层次,看任何一层都推不出另外两层的情况。

层次

观测对象

典型失效

声明层

nginx / 服务端配置里写了什么

配了混合组,运行环境不支持

协商层

握手实际协商出的 group

静默降级为经典曲线,日志无异常

应用层

密钥派生是否真的混合

平台层没走 PQ,应用层兜住了

三层各失败各的。只盯着其中一层看,结果几乎总是“正常”,这也是 PQC 迁移的监控和常规 TLS 监控最不一样的地方:常规监控看的是连通性,PQC 还得看流量走了哪条路径。

本系列第 3、4 篇讲的是算法在硬件上的资源与功耗,本篇回到线上,谈迁移之后怎么证明它真的生效了。


2. 声明层:静态解析要配着能力探测一起用

tools/scan-crypto-assets.cjs 干两件事。

一是静态解析 nginx 站点配置,把 ssl_protocolsssl_ecdh_curvessl_ciphers 和证书路径取出来。二是能力探测,执行 openssl versionopenssl list -tls-groups,看这套环境的 OpenSSL 认不认识混合组。

第二步最容易被省掉,也最关键。判定逻辑长这样:

配置里声明了混合组、环境也支持混合组,两个条件同时成立才算 ready。只看配置的话,“配了但没生效”会被一路判成已迁移。

FIBEMATE 生产服务器 2026-09-06 的实测结果是:识别出 4 个 endpoint、3 个 pm2 进程、2 张证书,OpenSSL 版本 3.0.13,低于 ML-KEM 需要的 3.5,所以 hybrid_tls_ready 为 false。

这里还有个踩得很多的坑。openssl version 报的是 shell 的 OpenSSL,跟 nginx 实际链接的那个不一定是一回事。要看 nginx 链接的版本,得用:

两者不一致时以 nginx 链接的为准。

顺带说明这个工具在这件事上的取舍:它的能力探测读的是 shell 的 OpenSSL 版本,拿它当环境能力的代理指标,没有去解析 nginx 的编译期链接信息。用系统包管理器统一安装的环境,两者通常一致;自己编译 nginx 或者发行版静态链接了 OpenSSL 的,这个代理就可能失真。所以它更适合放在 CI 里做配置漂移检查,生产环境的最终核验还是建议看 nginx -V 的输出。


3. 协商层:问号前缀挡住了宕机,也顺手盖住了降级

先看这行配置:

X25519MLKEM768 就是 X-Wing,X25519 加 ML-KEM-768,code point 0x11ec,IANA TLS NamedGroup #4588。

前面那个问号是 OpenSSL 3.3 引入的写法:碰到不认识的组就跳过,不让 nginx 直接起不来。不加这个前缀,在没有 ML-KEM 的构建上会报:

这个前缀该加,它挡掉了“配置一上线服务就挂”这种最坏结果。但代价也很直接:它只保证不宕机,不保证 PQ 真的生效。没有 ML-KEM 的构建会静默退回经典曲线,error.log 里一行异常都不会有。

于是就有了一种极难发现的失效。服务一切正常,握手成功率 100%,仪表盘全绿,只是从头到尾走的都是 X25519。活儿等于白干,而且没有任何一个告警会告诉你。

要发现它只能实测协商结果:

这条命令得进定期巡检,不能只在部署后跑一次。环境升级、nginx 重建、配置回滚,任何一个都可能改掉协商结果。


4. 应用层:平台层没就绪时的兜底

平台层路线(路径 A,nginx 原生 NamedGroup)卡在系统级依赖上:要把 nginx 链接的 OpenSSL 升到 3.5 以上,这是系统级变更,得先在 staging 上验兼容性再单独排期,现有 nginx 版本是 1.30.1。

在那之前,平台层的后量子保护由应用层的混合 KEX 顶上,也就是路径 C-2:

组合

SM2 + ML-KEM-768

编号

IANA #4590(Informational I-D)

与 #4588 的区别

#4588 = X25519 + ML-KEM,国际通用;#4590 = SM2 + ML-KEM,适配国内商用密码规范与等保测评场景

承载方式

TLS Exporter + HTTP POST,不依赖 TLS 栈改动

握手原语

e2e-init / e2e-respond / e2e-poll / e2e-msg / e2e-fetch

密钥派生

HKDF(SM2_ECDH ‖ MLKEM_SS)

公钥载荷

1253 B

测试

E2E 900/900 全绿,p95 78.5 ms,集成测试 10/10 通过

状态

2026-07-16 集成至 reg-server,正式上线

这条路的价值不只是“先跑起来”。它不依赖 TLS 栈和浏览器实现,所以在平台层被 OpenSSL 版本卡住的时候,仍然能提供后量子保护。代价是它只覆盖自己的协议路径,浏览器直连的静态资源不在保护范围内。两条路径的保护范围不一样,不能互相充抵。


5. 埋点:四个字段决定能不能算出静默降级率

可观测性是埋点阶段的事,排障阶段才想起来加字段就补不回来了。

nginx 可以把协商结果透传给后端:

$ssl_curve 是握手实际协商出来的曲线,不是配置里写的那条,它就是用来区分声明层和协商层的变量。建议落这几个握手日志字段:

字段

含义

来源

group_declared

配置声明的首选混合组

静态解析

negotiated_group

实际协商结果

$ssl_curve

app_hybrid

应用层是否走了混合 KEX

应用埋点

handshake_ms

握手耗时

计时

四个字段齐了,核心指标才算得出来:

这几个指标里,静默降级率建议优先建。它是唯一能同时覆盖声明层和协商层不一致的指标,另外几项各自都照不出这个问题。

剩下三个各有各的用处。混合握手成功率用来发现兼容性问题,比如老客户端或者中间盒。客户端混合组分布用来判断真实覆盖率,避免出现服务端支持了但没人用的情况。p95 握手耗时要盯,是因为混合握手的 ClientHello 明显变大(ML-KEM 公钥 1184 B),放大和分片带来的延迟回归得看住。


6. 策略门禁能拦什么,拦不了什么

tools/check-crypto-policy.cjs 负责在部署前挡住密码配置漂移:

策略

内容

级别

P1

禁用 TLS 1.0 / 1.1

error

P1

未启用 TLS 1.3

warn

P2

若 OpenSSL ≥ 3.5,必须配置混合组

error

P3

证书 RSA < 2048 位

error

有 error 级违规就 process.exit(1)。另一道闸是 deploy/pqc-deploy.sh --check,OpenSSL 低于 3.5 时拒绝改动生产配置,2026-09-06 实测 exit 3,拦住了。

CI 那边是 .github/workflows/pqc-migration-verify.yml,跑三个场景:语法检查、场景 A(含混合组的配置应当通过策略校验)、场景 B(缺混合组应当被 P2 拦下,用来确认门禁真的会响)。

门禁的能力边界也得讲清楚。

CI 跑的是合成配置。GitHub runner 连不到生产服务器,所以验的是扫描器和策略逻辑本身,不是真实协商结果。

配置漂移拦得住,运行期降级拦不住。配置写对了但环境不支持,静态检查照样全绿,第 3 节那个问号前缀的场景就正好落在门禁的盲区里。

策略约束的是目标态,证明不了当前态。P2 只在 OpenSSL 3.5 及以上才生效,环境没升级的时候它一声不吭。

所以门禁和运行时观测是互补的两件事,一个防配置写错,一个防环境不支持,谁也替不了谁。


7. 边界声明

  • 生产域名 fibemate.net 还没灰度平台层混合 TLS,当前默认 TLS 1.3 + X25519。本篇给的是检测能力和建设路径,不是生产运行数据。
  • 平台层路径 A 卡在 OpenSSL 3.5 升级上(当前 nginx 链接 3.0.13),属系统级变更,尚未排期。
  • 应用层路径 C-2 已上线(900/900、p95 78.5 ms),保护范围限于自身协议路径,不等价于全站混合 TLS。
  • 扫描器实测数据是 2026-09-06 的快照,环境一变就失效,要重跑不能复用。
  • CI 场景用的是合成配置,不代表生产协商结果。
  • 静默降级率的 SQL 是设计示例,还没在生产埋点体系上跑通。
  • SM2-MLKEM-768 对应的 IANA #4590 是 Informational I-D,非标准跟踪状态,兼容性需自行验证。

8. 结语

PQC 迁移验收难在一个地方:“没生效”和“没出问题”在监控上长得一模一样。

办法倒不复杂,把声明、协商、应用三层分别埋点,然后专门算它们之间的差集。

这套投入平时看不出回报,回报都在两个时刻:环境升级之后,配置回滚之后。这两件事都会改变协商结果,也都不会在错误日志里留下任何痕迹。


参考实践

  • 主仓库:github.com/Lennonhaha/fibemate · 官网 fibemate.net
  • 资产扫描与能力探测:tools/scan-crypto-assets.cjs
  • 策略门禁:tools/check-crypto-policy.cjs(P1/P2/P3,error → exit 1)
  • 部署前置校验:deploy/pqc-deploy.sh --check(低于 3.5 → exit 3)
  • 混合 TLS 配置模板:deploy/pqc-nginx-hybrid.conf.example
  • CI 验证:.github/workflows/pqc-migration-verify.yml
  • 就绪度全景:docs/pqc-readiness.md

词汇注释

  • X25519MLKEM768(X-Wing):X25519 与 ML-KEM-768 的混合密钥交换,code point 0x11ec,IANA TLS NamedGroup #4588。
  • SM2-MLKEM-768:SM2 与 ML-KEM-768 的混合,IANA #4590(Informational I-D),适配国内商用密码规范。
  • 问号前缀:OpenSSL 3.3+ 语法,未知组自动跳过而非拒绝启动,防宕机但不保证生效。
  • 静默降级:配置声明了混合组,运行环境不支持,实际协商为经典曲线且无任何错误日志。
  • TLS Exporter:从 TLS 握手导出密钥材料的标准机制,应用层混合 KEX 以此绑定会话。

FIBEMATE · 开源后量子密码(PQC)工程验证平台 · fibemate.net · github.com/Lennonhaha/fibemate


本文工具与数据均来自开源仓库 fibemate,扫描器、策略门禁与配置模板可自由获取与核对。转载请注明出处。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 1. 配置上线了,不等于混合密钥交换在跑
  • 2. 声明层:静态解析要配着能力探测一起用
  • 3. 协商层:问号前缀挡住了宕机,也顺手盖住了降级
  • 4. 应用层:平台层没就绪时的兜底
  • 5. 埋点:四个字段决定能不能算出静默降级率
  • 6. 策略门禁能拦什么,拦不了什么
  • 7. 边界声明
  • 8. 结语
    • 参考实践
    • 词汇注释
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档