关于 FIBEMATE:FIBEMATE 是一个开源的后量子密码(PQC)工程验证平台,覆盖算法元数据注册表、CBOM 盘点、CI 策略门禁、KAT 自测与硬件加速基准五条流水线。本篇的数据与工具全部来自主仓库 github.com/Lennonhaha/fibemate 的
tools/、deploy/与docs/pqc-readiness.md,均已在生产服务器上实测运行。官网:fibemate.net
多数团队的 PQC 验收止步于一句“配置已上线”。问题在于混合密钥交换横跨三个彼此独立的层次,看任何一层都推不出另外两层的情况。
层次 | 观测对象 | 典型失效 |
|---|---|---|
声明层 | nginx / 服务端配置里写了什么 | 配了混合组,运行环境不支持 |
协商层 | 握手实际协商出的 group | 静默降级为经典曲线,日志无异常 |
应用层 | 密钥派生是否真的混合 | 平台层没走 PQ,应用层兜住了 |
三层各失败各的。只盯着其中一层看,结果几乎总是“正常”,这也是 PQC 迁移的监控和常规 TLS 监控最不一样的地方:常规监控看的是连通性,PQC 还得看流量走了哪条路径。
本系列第 3、4 篇讲的是算法在硬件上的资源与功耗,本篇回到线上,谈迁移之后怎么证明它真的生效了。
tools/scan-crypto-assets.cjs 干两件事。
一是静态解析 nginx 站点配置,把 ssl_protocols、ssl_ecdh_curve、ssl_ciphers 和证书路径取出来。二是能力探测,执行 openssl version 和 openssl 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 的输出。
先看这行配置:
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 重建、配置回滚,任何一个都可能改掉协商结果。
平台层路线(路径 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 版本卡住的时候,仍然能提供后量子保护。代价是它只覆盖自己的协议路径,浏览器直连的静态资源不在保护范围内。两条路径的保护范围不一样,不能互相充抵。
可观测性是埋点阶段的事,排障阶段才想起来加字段就补不回来了。
nginx 可以把协商结果透传给后端:
$ssl_curve 是握手实际协商出来的曲线,不是配置里写的那条,它就是用来区分声明层和协商层的变量。建议落这几个握手日志字段:
字段 | 含义 | 来源 |
|---|---|---|
group_declared | 配置声明的首选混合组 | 静态解析 |
negotiated_group | 实际协商结果 | $ssl_curve |
app_hybrid | 应用层是否走了混合 KEX | 应用埋点 |
handshake_ms | 握手耗时 | 计时 |
四个字段齐了,核心指标才算得出来:
这几个指标里,静默降级率建议优先建。它是唯一能同时覆盖声明层和协商层不一致的指标,另外几项各自都照不出这个问题。
剩下三个各有各的用处。混合握手成功率用来发现兼容性问题,比如老客户端或者中间盒。客户端混合组分布用来判断真实覆盖率,避免出现服务端支持了但没人用的情况。p95 握手耗时要盯,是因为混合握手的 ClientHello 明显变大(ML-KEM 公钥 1184 B),放大和分片带来的延迟回归得看住。
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 及以上才生效,环境没升级的时候它一声不吭。
所以门禁和运行时观测是互补的两件事,一个防配置写错,一个防环境不支持,谁也替不了谁。
PQC 迁移验收难在一个地方:“没生效”和“没出问题”在监控上长得一模一样。
办法倒不复杂,把声明、协商、应用三层分别埋点,然后专门算它们之间的差集。
这套投入平时看不出回报,回报都在两个时刻:环境升级之后,配置回滚之后。这两件事都会改变协商结果,也都不会在错误日志里留下任何痕迹。
tools/scan-crypto-assets.cjstools/check-crypto-policy.cjs(P1/P2/P3,error → exit 1)deploy/pqc-deploy.sh --check(低于 3.5 → exit 3)deploy/pqc-nginx-hybrid.conf.example.github/workflows/pqc-migration-verify.ymldocs/pqc-readiness.md0x11ec,IANA TLS NamedGroup #4588。FIBEMATE · 开源后量子密码(PQC)工程验证平台 · fibemate.net · github.com/Lennonhaha/fibemate
本文工具与数据均来自开源仓库 fibemate,扫描器、策略门禁与配置模板可自由获取与核对。转载请注明出处。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。