RFC 10042: Post-Quantum/Traditional Hybrid Key Exchange with the Module-Lattice-Based Key-Encapsulation Mechanism for Use in SSH の通信シーケンスとメッセージ構造の整理

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

本記事はAIを利用して作成した技術解説・実装例です。掲載するコードや手順は一次情報を基に構成していますが、筆者による実機での動作確認は行っていません。環境やバージョンによって動作が異なる場合があります。

Secure Shell(SSH)プロトコルは、従来の楕円曲線暗号(ECDH)などの鍵共有方式を長年利用してきました。しかし、将来的に十分な性能を持つ量子コンピュータが実現した場合、これまでの方式は安全性が脅かされる可能性があります。こうした懸念に対して、攻撃者が暗号化された通信を保存しておき、後から量子コンピュータで復号を試みる「今記録し、後で復号する(Harvest now, decrypt later)」攻撃への対策が急務となっています。

RFC 10042 は、こうした課題に対応するため、耐量子計算機暗号であるModule-Lattice-Based Key-Encapsulation Mechanism(ML-KEM)と、従来の楕円曲線ディフィー・ヘルマン(ECDH)鍵共有を組み合わせた「Post-Quantum/Traditional(PQ/T)Hybrid key exchange」の仕組みをSSHのトランスポート層プロトコルへ導入するための仕様を定義しています。 、一次情報に基づき、このハイブリッド鍵交換の抽象構造、メッセージのやり取り、具体的な方式のバリエーション、および共有秘密の生成方法について整理します。


1. 背景とハイブリッド鍵交換の基本概念

従来のSSH鍵交換では、離散対数問題の困難性に基づいたECDH方式(RFC 5656やRFC 8731など)が利用されてきました。これに対し、一次情報ではNISTで標準化されたML-KEMと古典的アルゴリズムを組み合わせたPQ/Tハイブリッド鍵交換を定義しています。

ハイブリッド方式における個別の鍵交換スキームのセキュリティは互いに独立しています。つまり、PQ/Tハイブリッド鍵交換方式は、構成要素の中で最も安全な鍵交換スキームと同等以上に安全性が確保される仕組みになっています。

NISTの枠組みにおけるKEM(Key-Encapsulation Mechanism)は、主に以下の3つのアルゴリズムで構成されます。

  • 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 の3つのバリエーションが存在します。


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

メッセージ番号として 30 が割り当てられた SSH_MSG_KEX_HYBRID_INIT を用いて、クライアントは以下の文字列データを送信します。

  • byte: SSH_MSG_KEX_HYBRID_INIT (30)

  • string: C_INIT

ここで、C_INIT は2つのエフェメラル公開鍵の結合値であり、C_INIT = C_PK2 || C_PK1|| は結合を表す)として構成されます。

  • C_PK1: 従来の古典的鍵交換(ECDHなど)のエフェメラル公開鍵。

  • C_PK2: 対応するポスト量子KEMの KeyGen から出力された公開鍵 pk

サーバからの返信メッセージ: SSH_MSG_KEX_HYBRID_REPLY

メッセージ番号として 31 が割り当てられた SSH_MSG_KEX_HYBRID_REPLY を用いて、サーバは以下のデータを返します。

  • byte: SSH_MSG_KEX_HYBRID_REPLY (31)

  • string: K_S(サーバの公開ホスト鍵)

  • string: S_REPLY

  • string: 交換ハッシュに対する署名

ここで、S_REPLYS_REPLY = S_CT2 || S_PK1 として構成されます。

  • S_PK1: 従来のエフェメラルECDHサーバ公開鍵。

  • S_CT2: サーバ側の Encaps アルゴリズムが生成したKEMの暗号文 ct(クライアントの公開鍵 C_PK2 に対して秘密をカプセル化したもの)。


3. 検証処理と安全性の確保

メッセージの送受信においては、長さを狙った攻撃(レングス・エクステンション攻撃など)を防ぐための厳格なチェックが義務付けられています。

  • サーバ側のチェック: サーバは S_CT2 を生成する前に、受信した C_INIT の長さが、ネゴシエートされた方式における各公開鍵(C_PK1 および C_PK2)の期待される長さの総和と一致していることを必ず(MUST)確認しなければなりません。また、FIPS 203で定義されているカプセル化鍵のチェックも実行する必要があります。失敗した場合は、SSH_MSG_DISCONNECT(理由: SSH_DISCONNECT_KEY_EXCHANGE_FAILED)を用いて接続を中断します。

  • クライアント側のチェック: クライアントは復号(デカプセル化)を行う前に、S_REPLY の長さが伝統的公開鍵 S_PK1 とML-KEM暗号文 S_CT2 の期待される長さの総和と一致していることを確認しなければなりません。長さの不一致や復号エラーが発生した場合は、同様に切断メッセージで接続をアボートします。


4. 定義されている具体的なハイブリッド方式

RFC 10042では、具体的な組み合わせとして以下の3つの方式名が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 の2つが確立されます。

最終的な共有秘密 K は、これら2つの共有秘密を結合したもののハッシュ値として算出されます。

$$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をコピーしました