本文へスキップ
ecdsa.com

X25519MLKEM768 と X25519 の比較|TLS のポスト量子鍵交換

ハイブリッドグループは ClientHello を約 1.2 KB 大きくする代わりに、記録されたトラフィックを将来の量子コンピューターから守ります。ブラウザー、OpenSSL、Go ではすでにデフォルトになっています。

X25519MLKEM768 と X25519 のどちらを使うかは、現在のあらゆる TLS 1.3 ハンドシェイクにおける鍵交換の選択です。X25519 単体は高速でデータも非常に小さいものの、量子コンピューターには破られます。つまり、今記録されたトラフィックが後から解読されるおそれがあります。X25519MLKEM768 は X25519 と ML-KEM-768 を組み合わせて実行するため、両方が破られない限り、セッションの機密性は保たれます。

比較表

X25519X25519MLKEM768
TLS のサポートされるグループx25519、29(0x001D)X25519MLKEM768、4588(0x11EC)、IANA 推奨
仕様RFC 7748、RFC 9846RFC 10024(2026年)、フレームワークは RFC 9954
構成要素X25519ML-KEM-768(FIPS 203)と X25519
クライアントのキーシェア(key share)32 バイト1,216 バイト(ML-KEM のカプセル化鍵 1,184 + 32)
サーバーのキーシェア32 バイト1,120 バイト(ML-KEM の暗号文 1,088 + 32)
鍵スケジュールに入る共有秘密32 バイト64 バイト(ML-KEM の共有秘密が先、X25519 が後)
量子耐性なしあり(ML-KEM-768 が破られない限り)
古典的な安全性X25519ML-KEM が破られた場合でも、少なくとも X25519 と同等
ハンドシェイクあたりの CPU コスト(OpenSSL 3.6.5)X25519 の演算が毎秒約 52,000 回鍵生成、カプセル化、デカプセル化がそれぞれ毎秒約 19,000〜24,000 回
以下で実測した ClientHello306 バイト1,484 バイト
以下で実測した ServerHello122 バイト1,210 バイト

スループットは Apple M4 Max の 1 コアで openssl speed を使って計測し、ハンドシェイクのサイズは以下のキャプチャから得たものです。

今ハイブリッドが必要な理由

鍵交換は harvest now, decrypt later の脅威にさらされています。攻撃者は暗号化されたセッションを今のうちに記録しておき、暗号を破れる規模の量子コンピューターが登場した時点で、記録した X25519 の鍵交換からセッション鍵を復元して解読します。記録された鍵交換は 1 つずつ個別に破れるため、前方秘匿性は役に立ちません。そのような量子コンピューターが登場した後も機密性を保たなければならないデータは、すでに危険にさらされています。署名はもう少し待てる一方で、鍵交換の移行が先に進んだのはこのためです。

ハイブリッド設計は、逆方向のリスクにも備えています。ML-KEM は 2024年8月に標準化されたばかりで、X25519 に比べると歴史が浅いため、数学的な破綻や実装上の欠陥が見つかる可能性も否定できません。X25519MLKEM768 は 2 つの共有秘密を連結して TLS の鍵スケジュールに入れるため、攻撃者は両方を破らなければなりません。RFC 10024 では、このグループについては ML-KEM のキーシェアと共有秘密を先に置きます。これは、ECDH を先に置く NIST 曲線のハイブリッド(SecP256r1MLKEM768、0x11EB と SecP384r1MLKEM1024、0x11ED)とは逆の順序です。

通信上の変化

クライアントは 32 バイトではなく 1,216 バイトのキーシェアを送るため、一般的な ClientHello は約 300 バイトから約 1.5 KB に増え、ブラウザーが付けるほかの拡張と合わせると 1 つのネットワークパケットに収まらなくなります。サーバーは 1,120 バイトのキーシェアで応答します。OpenSSL 3.6.5 でキャプチャした Cloudflare との実際のハンドシェイクで、その違いを確認できます。

OpenSSL 3.6.5:グループごとの TLS 1.3 ハンドシェイク
echo | openssl s_client -connect cloudflare.com:443 -servername cloudflare.com -groups X25519MLKEM768 -brief 2>&1 | grep -E "Protocol|group"
echo | openssl s_client -connect cloudflare.com:443 -servername cloudflare.com -groups X25519MLKEM768 -msg 2>&1 | grep -E "ClientHello|ServerHello"
echo | openssl s_client -connect cloudflare.com:443 -servername cloudflare.com -groups X25519 -msg 2>&1 | grep -E "ClientHello|ServerHello"
出力(2026年10月20日、長さは 16 進数)
Protocol version: TLSv1.3
Negotiated TLS1.3 group: X25519MLKEM768
>>> TLS 1.3, Handshake [length 05cc], ClientHello
<<< TLS 1.3, Handshake [length 04ba], ServerHello
>>> TLS 1.3, Handshake [length 0132], ClientHello
<<< TLS 1.3, Handshake [length 007a], ServerHello

つまり、ClientHello は 1,484 バイト対 306 バイト、ServerHello は 1,210 バイト対 122 バイトです。ClientHello が大きくなったことで、メッセージが 1 回の TCP 読み取りや 1 つのパケットで届くと想定していたサーバーやミドルボックスのバグが表面化しました。Chrome がバージョン 124(2024年)でハイブリッドの Kyber キーシェアをデフォルトで有効にした際には、いくつかのファイアウォール製品やプロキシ製品が修正を迫られました。この種の問題は tldr.fail にまとめられています。Cloudflare と Google は、追加のバイトによってハンドシェイクのレイテンシーの中央値が数パーセント増えたと報告していますが、これは TLS 1.3 自体が削減したラウンドトリップに比べればはるかに小さな影響です。

導入状況

  • ブラウザー:Chrome と Edge はバージョン 131(2024年11月)から、Firefox はデスクトップ版の 132 から、Safari と Apple のシステム TLS は iOS 26 と macOS 26(2025年)から、X25519MLKEM768 をデフォルトで提示しています。以前使われていた標準化前の X25519Kyber768Draft00(0x6399)は非推奨になりました。
  • ライブラリ:OpenSSL 3.5(2025年4月)は、X25519MLKEM768 と X25519 のキーシェアをデフォルトで送信します。Go 1.24 は crypto/tls でこれをデフォルトで有効にしており、JDK 27(2026年9月、JEP 527)はデフォルトでこれを最優先で提示します。BoringSSL、rustls、NSS も対応しています。
  • サーバーと CDN:Cloudflare、Google などの大手プロバイダーは、対応するクライアントとの間でこれをネゴシエートします。nginx、Apache、HAProxy は、リンクされた OpenSSL からこの対応を引き継ぎます。
  • SSH:同等の mlkem768x25519-sha256 が、OpenSSH 10.0 以降のデフォルトです(RFC 10042)。

ブラウザーのポスト量子チェックで、お使いのブラウザーが何をネゴシエートしているかを確認できます。

どちらを選ぶべきか

  • 公開 HTTPS と API:X25519MLKEM768 を 1 番目、X25519 を 2 番目に提示します。最新のクライアントはすべてハイブリッドをネゴシエートし、古いクライアントはフォールバックします。
  • 内部のサービスメッシュと mTLS:デフォルトでハイブリッドを使います。長期間の機密性が求められるデータでは、なおさらです。
  • FIPS を重視する環境:モジュールの承認済みリストが NIST 曲線を要求する場合は、SecP256r1MLKEM768 または SecP384r1MLKEM1024 を使います。ML-KEM が承認済みの構成要素である環境では、X25519MLKEM768 も要件を満たします。
  • 1 パケットも無駄にできない制約の多い回線:まず計測してください。ハイブリッドで増えるのは方向ごとに 1 パケットで、通常は許容範囲です。
  • X25519 単体:ハイブリッドを使えない相手に限って使います。新規の導入で意図的に選んではいけません。

移行時の注意点

  1. TLS ライブラリをアップグレードする(OpenSSL 3.5 以降、Go 1.24 以降、最新の BoringSSL または rustls):OpenSSL 3.5 では、デフォルトのグループにすでにハイブリッドが含まれています。
  2. グループを明示的に設定している場合は、ハイブリッドを追加する:たとえば nginx では ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1;、OpenSSL の設定ファイルでは Groups = X25519MLKEM768:X25519:P-256 とします。
  3. サーバーだけでなく経路全体をテストする:ロードバランサー、WAF、TLS を検査するプロキシは、複数のパケットや読み取りに分割された ClientHello を処理できなければなりません。これらをアップグレードした後は再テストしてください。
  4. ネゴシエートされる内容を確認する:openssl s_client -groups X25519MLKEM768 やブラウザーの開発者ツールで確認し、ハイブリッドのハンドシェイクの割合を監視します。
  5. 署名側は別に計画する:ハイブリッドが守るのは機密性だけです。WebPKI にポスト量子署名が導入されるまで、証明書とハンドシェイクの署名は古典的な方式のままです。

参考資料

すべての比較