RFC 10042:基于模块格密码的密钥封装机制用于SSH的后量子/传统混合密钥交换的通信序列与消息结构整理

ネットワーク・RFCカテゴリを表すパンダのイラスト 网络・RFC

本文是利用AI生成的的技术解析与实现示例。所发布的代码与步骤基于第一手资料构建,但未经作者在真实设备上进行运行验证。根据环境和版本的不同,实际运行表现可能会有所差异。

Secure Shell(SSH)协议多年来一直使用传统的椭圆曲线密码学(ECDH)等密钥交换方式。然而,如果未来实现具备足够性能的量子计算机,以往的方式可能会面临安全性受到威胁的风险。针对这些担忧,迫切需要采取对策来防范攻击者保存加密通信、随后试图用量子计算机进行解密的“现在截获,以后解密(Harvest now, decrypt later)”攻击。

为了应对这些挑战,RFC 10042 定义了一套规范,将抗量子计算密码——基于模块格的密钥封装机制(ML-KEM)与传统的椭圆曲线迪菲-赫尔曼(ECDH)密钥交换相结合,引入到 SSH 传输层协议中,实现了“Post-Quantum/Traditional(PQ/T)Hybrid key exchange”。 基于第一手资料,本文将对这种混合密钥交换的抽象结构、消息交互、具体的变体方式以及共享秘密的生成方法进行整理。


1. 背景与混合密钥交换的基本概念

在传统的 SSH 密钥交换中,一直使用基于离散对数问题困难性的 ECDH 方式(如 RFC 5656 和 RFC 8731 等)。与之相对,第一手资料定义了将 NIST 标准化的 ML-KEM 与经典算法相结合的 PQ/T 混合密钥交换。

混合方式中各个独立密钥交换方案的安全性是相互独立的。也就是说,PQ/T 混合密钥交换方案被设计为能够确保其安全性等同于或高于其组成部分中最安全的密钥交换方案。

在 NIST 的框架下,KEM(Key-Encapsulation Mechanism)主要由以下三种算法构成:

  • KeyGen() -> (pk, sk): 生成公钥 pk 和私钥 sk 的概率算法。

  • Encaps(pk) -> (ct, ss): 以公钥 pk 作为输入,输出密文 ct 和共享秘密 ss 的概率算法。

  • Decaps(sk, ct) -> ss: 以私钥 sk 和密文 ct 作为输入,输出共享秘密 ss(或错误值)的算法。

KEM 的主要安全需求包括针对自适应选择密文攻击的不可区分性(IND-CCA2)以及针对选择明文攻击的不可区分性(IND-CPA)。RFC 10042 中采用的 ML-KEM 是在 2024 年被标准化为 FIPS 203 的算法,作为参数,它存在 ML-KEM-512、ML-KEM-768 和 ML-KEM-1024 三种变体。


2. 通信序列与消息结构的规范

在 PQ/T 混合密钥交换中,定义了新的消息来代替传统的 SSH_MSG_KEXDH_INITSSH_MSG_KEX_ECDH_INIT

以下是客户端和服务器之间进行的 PQ/T 混合密钥交换消息流的整体概览。

sequenceDiagram
    participant Client as SSH Client
    participant Server as SSH Server
    Client->>Server: SSH_MSG_KEX_HYBRID_INIT (C_INIT = C_PK2 || C_PK1)
    Server->>Client: SSH_MSG_KEX_HYBRID_REPLY (K_S, S_REPLY = S_CT2 || S_PK1, Signature)

客户端发送的消息: SSH_MSG_KEX_HYBRID_INIT

使用分配了消息编号 30SSH_MSG_KEX_HYBRID_INIT,客户端发送以下字符串数据:

  • byte: SSH_MSG_KEX_HYBRID_INIT (30)

  • string: C_INIT

在此,C_INIT 是两个临时公钥的连接值,构成为 C_INIT = C_PK2 || C_PK1(其中 || 表示连接)。

  • C_PK1: 传统经典密钥交换(如 ECDH 等)的临时公钥。

  • C_PK2: 对应的后量子 KEM 的 KeyGen 输出的公钥 pk

服务器回复的消息: SSH_MSG_KEX_HYBRID_REPLY

使用分配了消息编号 31SSH_MSG_KEX_HYBRID_REPLY,服务器返回以下数据:

  • byte: SSH_MSG_KEX_HYBRID_REPLY (31)

  • string: K_S(服务器的公有主机密钥)

  • string: S_REPLY

  • string: 对交换哈希的签名

在此,S_REPLY 构成为 S_REPLY = S_CT2 || S_PK1

  • S_PK1: 传统的临时 ECDH 服务器公钥。

  • S_CT2: 服务器侧的 Encaps 算法生成的 KEM 密文 ct(对客户端公钥 C_PK2 进行了秘密封装的内容)。


3. 验证处理与安全性保障

在消息的发送和接收过程中,必须进行严格的检查,以防止针对长度的攻击(如长度扩展攻击等)。

  • 服务器侧的检查: 服务器在生成 S_CT2 之前,必须(MUST)确认接收到的 C_INIT 的长度与商定的协商方式中各个公钥(C_PK1C_PK2)的预期长度总和相匹配。此外,还必须执行 FIPS 203 中定义的封装密钥检查。如果失败,则使用 SSH_MSG_DISCONNECT(原因: SSH_DISCONNECT_KEY_EXCHANGE_FAILED)中断连接。

  • 客户端侧的检查: 客户端在执行解密(解封装)之前,必须确认 S_REPLY 的长度与传统公钥 S_PK1 和 ML-KEM 密文 S_CT2 的预期长度总和相匹配。如果发生长度不匹配或解密错误,同样会通过断开连接消息中止连接。


4. 定义的具体混合方式

在 RFC 10042 中,以下三种组合的具体方式名称已在 IANA 注册。这些名称将用于 SSH_MSG_KEXINIT 中。

  1. mlkem768nistp256-sha256

    • 传统密钥交换: NIST P-256 曲线(ecdh-sha2-nistp256

    • 后量子 KEM: ML-KEM-768

    • 哈希函数: SHA-256

  2. mlkem1024nistp384-sha384

    • 传统密钥交换: NIST P-384 曲线(ecdh-sha2-nistp384

    • 后量子 KEM: ML-KEM-1024

    • 哈希函数: SHA-384

  3. mlkem768x25519-sha256

    • 传统密钥交换: Curve25519(curve25519-sha256

    • 后量子 KEM: ML-KEM-768

    • 哈希函数: SHA-256


5. 共享秘密(Shared Secret K)的导出方法

在混合密钥交换中,会确立两个共享秘密:从经典 ECDH 获得的共享秘密 K_CL,以及从 ML-KEM 获得的后量子共享秘密 K_PQ

最终的共享秘密 K 计算为这两个共享秘密连接后的哈希值。

$$K = text{HASH}(K_{text{PQ}} parallel K_{text{CL}})$$

虽然在 TLS 1.3(RFC 9954)等协议中直接将连接后的秘密输入到密钥调度中,但本规范采取了符合 SSH 密钥导出方法的方式,即在连接后通过一次哈希函数进行处理。

此外,传统方式中 ECDH 的共享秘密编码为整数(mpint),而本规范中则作为固定长度的大端字节数组处理(Curve25519 和 secp256r1 为 32 字节,secp384r1 为 48 字节)。


6. 密钥导出与哈希计算(H)的输入要素

密钥交换方法的哈希函数 $H$ 是通过对连接了以下要素的数据进行哈希计算来获取的:

  • 客户端标识字符串 V_C

  • 服务器标识字符串 V_S

  • 客户端的 SSH_MSG_KEXINIT 有效载荷 I_C

  • 服务器的 SSH_MSG_KEXINIT 有效载荷 I_S

  • 服务器的公有主机密钥 K_S

  • 客户端消息字符串 C_INIT

  • 服务器消息字符串 S_REPLY

  • SSH 共享秘密 K

加密密钥将根据此哈希结果 H 和共享秘密 K 导出。需要说明的是,关于消息大小,前提是在传统 SSH 规范(RFC 4253)规定的最小支持有效载荷长度(32768 字节以下)的范围内进行操作。


参考信息

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

标题和URL已复制