有人说:“换成后量子算法以后,把 ML-DSA 签名加进握手,就能替代密钥交换。”这是把两件不同操作放在一个盒子里:ML-KEM 用于建立双方一致的秘密,ML-DSA 用于证明特定消息由签名密钥持有者授权。KEM 共享秘密匹配也不会自动认证发送密文的一端;签名验真也不会自动证明自己与另一端共享了对称记录密钥。旧的量子风险解释应具体指出 RSA/ECDH 的困难假设面临哪类威胁,不能因为“后量子”三个字就宣称工程已经抵抗了未来所有攻击。

KEM 的四个输入输出

受信任的接收方发布 ML-KEM 公钥,保留私钥。发送方拿到已正确绑定身份的公钥后执行封装:输入公钥与随机源,输出可发送的密文 cipherText 以及自己的共享秘密 sharedSecret;接收方对同一密文用私钥解封装,得到相同共享秘密。发错私钥或改封装密文时,许多 KEM 采用隐式拒绝:返回不同的秘密而非清晰抛出“认证失败”。随后必须在有身份约束的协议里通过 transcript/Finished 或应用认证发现双方秘密不一致,不能把“函数没有报错”写成“双方已认证”。

ML-DSA 则取私钥与指定消息字节生成签名,任意拿到正确公钥的人对那些字节验签;它自己不产生双方会话秘密。两套密钥用途和泄漏影响要分别管理。一个“混合”握手可能将经典 X25519 的 32 字节共享秘密与 ML-KEM 的 32 字节结果通过指定格式和 HKDF 结合,保证双方按同一 transcript、顺序和身份规则处理;真实协议还须指定算法协商、降级防护、证书、重试和 KEM 密文绑定,不能把简单拼接函数称为完整 TLS。

1
2
3
4
5
6
7
接收方:ML-KEM keygen ─► publicKey(给对方)/ secretKey(本地)
发送方:encaps(publicKey) ─► cipherText(发出) + secret-A(本地)
接收方:decaps(cipherText,secretKey) ─► secret-B;核对 A 与 B 用于后续密钥确认

另一条线:X25519 临时 DH ─┐
ML-KEM 解封装 ───┴─► HKDF(info + transcript) ─► 方向性密钥
身份认证:ML-DSA 或其他被信任签名/证书机制 ─► 绑定握手身份

examples/cryptography/E02_post_quantum.mjs 使用冻结的成熟 JS ML-KEM-768/ML-DSA-65 真原语,先核对共享秘密相等、错私钥和改密文各得到不同的秘密;真签名对原消息验真、改消息不通过。另用 Node 真 X25519 + hkdfSync,在这份本地自定格式中混合两种秘密和公开的合成 transcript,让两端导出一致 32 字节密钥:

先按仓库内 examples/cryptography/README.md 完成环境准备;以下命令从仓库根目录执行。

1
2
node examples/cryptography/E02_post_quantum.mjs
node --test examples/cryptography/E02_post_quantum.test.mjs

原语正反例 1 项测试通过,tls_hybrid_handshake_executed=false。还没有将 FIPS 正式 KAT 每字节核对,没有抓实际 TLS 混合握手或真实 PKI 签名,也没有断言此库取得任何 NIST 认证。不得用“库可计算”替代“特定浏览器、服务器、fork 已启用并正确协商”,也不得把 ML-KEM 的密码学保密目标直接升级成真实订单交付。

练习及答案

画图题: 发送方 A 错把攻击者的 ML-KEM 公钥当服务公钥,解封装操作可成功发生在哪里?若将服务身份验证整段删掉,但双方 KEM 共享秘密一致,攻击者会怎样插进来?

答案: 发送方封装到攻击者公钥,攻击者用自己私钥解封并共享这个秘密;真实服务的私钥无法解出相同秘密。能与某个公钥算出相同秘密只证明你与该密钥的持有人共享,并未验证它是预期服务。需要将公钥/握手 transcript 绑定到可信的服务身份,否则中间人分别协商两组秘密。

实验变更题: 翻转 cipherText[7] 但不更换接收私钥,程序为何不能以“没有抛异常”判通过?另改 ML-DSA 消息尾字节但仍使用原签名,哪项操作应失败?

答案: 解封装可能返回不同共享秘密,双方若用它派生记录密钥,密钥确认或后续认证应失败;不能以返回值存在为成功标准。ML-DSA 对改后消息的公开验签应失败,正确 KEM secret 不替签名核对消息字节。

资料与导航