私たちが毎日使っている暗号技術には有効期限があります。予測は簡単ではありませんが、この先の15年から40年の間のどこかで、十分に強力な量子コンピュータが作られ、基本的に現在インターネット上にあるあらゆる暗号データを解読できるようになると予想されています。
幸い、ソリューションとしてポスト量子(PQ)暗号化があり、これは量子コンピュータの脅威に対しても安全な設計がなされています。わずか3か月前の2022年7月、AESとSHA2で知られる米国国立標準技術研究所(NIST)は、6年間の世界的なコンテストの後、どのポスト量子暗号を標準化するかを発表しました。NISTは2024年に最終規格を公開する予定ですが、ポスト量子暗号の早期採用を促進したいと考えています。
本日よりベータサービスとして、Cloudflareを通じて提供されるすべてのWebサイトとAPIは、ポスト量子ハイブリッド鍵合意をサポートしています。これはデフォルトで有効になっています1。オプトインは必要ありません。つまり、お使いのブラウザやアプリが対応していれば、当社のネットワークへの接続は、将来の量子コンピュータに対しても安全です。
当社は、このポスト量子暗号を無償で提供します。ポスト量子セキュリティは、インターネットの新しいベースラインとなるべきものだと考えているからです。
量子コンピュータの登場により、ポスト量子暗号の導入は当然のことと考えられますが、それでもリスクがないとは言い切れません。そもそも、これは新しい暗号です。何年もかけて精査しても、破滅的な攻撃が発見される可能性がないとは言えません。そのため、当社は、_ハイブリッド方式_をデプロイします。テストされてきた鍵同意と、ポスト量子セキュリティを追加する新しい鍵同意を組み合わせて導入しています。
主な心配は、これが単に実用的に思えるだけかもしれないことです。インターネットの安全性を確保するためのプロトコルは、このようなスムーズな移行を可能にするように設計されていますが、現実にはバグの多いコードが多く存在しています。例えば、ミドルボックスがポスト量子鍵の大きさに対応できないなど、ポスト量子鍵同意が新しいため、まだ観察されていない様々な理由で、ポスト量子の安全接続の試みが失敗する可能性もあります。このような問題があるからこそ、ポスト量子暗号を早期にデプロイし、ブラウザや他のクライアントと一緒に問題を発見し、解決していくことが重要だと考えています。
このブログでは、インターネットの安全性を確保するためのプロトコルであるTLSが、使用する暗号をスムーズかつ安全に移行できるように設計されていることを説明します。そして、当社がデプロイしたポスト量子暗号の技術的な詳細と、実際には、この移行がまったくもってスムーズにいかない可能性があることを説明します。このブログ記事の最後に、この新世代の暗号のテストに協力していただくことで、皆さんがより良い、ポスト量子セキュアなインターネットを構築できることを説明します。
TLS: Transport Layer Security (トランスポート層セキュリティ)
_セキュアな接続_を使用してWebサイトを閲覧しているとき、HTTP/1.1 または QUIC のいずれを使用している場合でも、その内部では Transport Layer Security (TLS) プロトコルが使用されています。今日、一般に使われているTLSには2つの主要なバージョンがあります。新しいTLS 1.3 (~90%) および古いTLS 1.2 (~10%) ですが、後者は減少傾向にあります。
TLS 1.3 はTLS 1.2 に比べて大きな改善です。ちょうどいいところでより速く、より安全に、よりシンプルに、よりフレキシブルになっています。このため、TLS 1.2 と比較して、TLS 1.3 にポスト量子セキュリティを追加することが容易になりました。今のところ、TLS 1.3 にポスト量子サポートを追加するだけにします。
では、TLSとはどのようなものなのでしょうか。目標は、ブラウザとWebサイトの間に、以下のような接続を設定することです。
機密性と完全性、誰もデータを読み取ったり、検出されずに改ざんしたりすることはできません。
真正性、偽サイトではなく、正しいWebサイトに接続していることを確認できます。
ビルディングブロック: AEAD、鍵合意、署名
この目標を達成するために、TLSでは3つの異なるタイプの暗号が使用されています。
対称暗号、より正確には Authenticated Encryption With Associated Data (AEAD) は、暗号技術の主力製品で、機密性と完全性を確保するために使用されます。これは単純な暗号化で、データの暗号化と復号化に使われる _単一の鍵_が存在します。正しい鍵がなければデータを復号化することはできず、暗号化されたデータを改ざんすると、復号化時にエラーとなります。
TLS 1.3では、ChaCha20-Poly1305、およびAES128-GCMが現在一般的に使用されています。量子攻撃に対してどうでしょうか。一見すると、 Groverのアルゴリズムから防御するために256ビットの共通鍵に切り替える必要があるように見えます。しかし、実際には Grover のアルゴリズムはうまく並列化できないので、現在デプロイされているAEADで十分です。
ですから、対称暗号で使用する共有鍵に合意できればよいわけです。しかし、どうすれば共有鍵を持てるのでしょうか。鍵を選んでサーバーに送るだけでは、盗聴する人はその鍵も知ることになります。それは不可能なことだと思うかもしれませんが、ここで非対称暗号のマジックが役に立ちます。
鍵合意は、鍵交換、_鍵配布_とも呼ばれますが、盗聴者が何も知ることなく二者が共有鍵に合意できる暗号プロトコルです。今日、 X25519 Elliptic Curve Diffie-Hellman プロトコル (ECDH) はTLS 1.3 で使われている事実上の標準鍵合意です。 X25519のセキュリティは、楕円曲線に対する離散対数問題に基づいています。この問題は、暗号学的に関連する量子コンピュータが Shorのアルゴリズムを用いて容易に解くことができるので、量子攻撃には脆弱です。ソリューションとしては、Kyberのようなポスト量子鍵合意を使用することです。
鍵合意は受動的な攻撃者からしか保護されません。メッセージを傍受して変更できる能動的な攻撃者 (MitM) は、サーバーとブラウザの両方で別々の共有鍵を確立し、通過するすべてのデータを再暗号化することができます。この問題を解決するためには、最後の暗号が必要です。
RSA や ECDSA などのデジタル署名アルゴリズムには、_公開鍵_と_プライベートキー_の2つの鍵があります。プライベートキーでのみ、メッセージの_署名_を作成できます。対応する公開鍵を持つ人は誰でも、特定のメッセージに対して署名が本当に有効かどうかを確認できます。これらのデジタル署名は、Webサイトの認証に使用されるTLS 証明書の重要な部分です。RSA もECDSA も量子攻撃には脆弱ですが、まだポスト量子署名に置き換えていません。それは認証の方が緊急性が低く、十分な大きさの量子コンピュータができるまでに置き換えればよいからです。現在脆弱な鍵合意で保護されているデータについては、今保存され、将来解読される可能性があります。時間があるとはいえ、ポスト量子認証のデプロイはかなりハードルが高くなることでしょう。
では、これらの要素がどのように組み合わされてTLSが構成されているのでしょうか。
TLS 1.3 のハイレベルな概要
High-level overview of TLS 1.3
TLS接続は、ハンドシェイクで始まり、これはサーバーの認証と共有鍵の導出に使用されます。ブラウザ (クライアント) は、まず_ClientHello_メッセージを送信し、サポートする AEAD、署名アルゴリズム、および鍵合意方法のリストを含みます。ラウンドトリップをなくすために、クライアントはサーバーが何をサポートしているかを推測し、1つ以上の_クライアント共有鍵_を送信して鍵合意を開始することが許可されています。この推測が正しい場合 (下図の左側) もあれば、クライアントは再試行しなければならない場合 (下図の右側) もあります。
サーバー認証型TLS 1.3 のプロトコルフロー。左側にサポートされているクライアントの共有鍵、右側に_HelloRetryRequest_がある。
鍵合意この相互作用の続きを説明する前に、鍵合意について掘り下げてみましょう。共有鍵とは何ですか。Kyber と X25519 の鍵合意の仕組みは異なっています 。前者は Key Encapsulation Mechanism (KEM) で、後者は Diffie-Hellman (DH) スタイルの合意です。後者の方がより柔軟ですが、TLSでは相違はありません。
TLSにおける KEM と Diffie-Hellman の鍵合意の形状は同じ。
どちらの場合も、クライアントは_クライアント共有鍵_をサーバーに送信します。この_クライアント共有鍵_から、サーバーは_共有鍵 ss_ を生成します。次にサーバーは _サーバー共有鍵_を返します。この鍵でクライアントも共有鍵を計算することができます。
TLS 1.3 のフローに戻ると、サーバーは _ClientHello_メッセージを受信すると、サポートするAEAD (暗号)、署名アルゴリズム、クライアント共有鍵を選択します。 _ServerHello_メッセージで返信し、選択したAEADと選択した鍵合意のための _サーバー共有鍵_を含みます。AEADと共有鍵がロックされると、サーバーはデータの暗号化を開始します (図では緑色で表示)。
認証AEADとサーバーの共有鍵とともに、サーバーはこれまでの通信のやり取りに関する署名、ハンドシェイク署名_を、署名の作成に使用した公開鍵の証明書 (チェーン) と共に送信します。これにより、クライアントはサーバーを認証することができます。クライアントは、公開鍵を認証した_認証局 (Let's Encrypt など) を信頼しているかどうか、またこれまでに送受信したメッセージについて署名が検証されているかどうかを確認します。これはサーバーを認証するだけでなく、ダウングレード攻撃からも保護することができます。
ダウングレード保護すべてのクライアントとサーバーを一度にポスト量子暗号にアップグレードすることはできません。一部のクライアントと一部のサーバーのみを対象に、ポスト量子暗号をサポートする移行期間が設けられます。TLS 1.3 の鍵合意ネゴシエーションはこれを可能にします。移行期間中、サーバーとクライアントは依然として非ポスト量子鍵合意をサポートし、必要に応じてそれに戻ることができます。
この柔軟性は素晴らしいのですが、同時に怖さもあります。クライアントとサーバーの両方がポスト量子鍵合意をサポートしている場合、それらがポスト量子鍵合意もネゴシエートしていることを確認したいところです。TLS 1.3 ではそうなっているのですが、その確認ができません。共有鍵、選択された共有鍵、サポートされる鍵合意のリストはすべて平文で送信されます。中間にいる攻撃者が、ポスト量子鍵合意を削除することは可能ではないでしょうか。これは_ダウングレード攻撃_と呼ばれるものです。
ここで、トランスクリプトが登場します。ハンドシェイクの署名が、これまでにサーバーが受信したメッセージと送信したメッセージのすべてについて取得されます。これには、サポートされている鍵合意と、選択された鍵合意が含まれます。攻撃者が、クライアントが送信するサポートされる鍵合意のリストを変更しても、サーバーは気づかないでしょう。しかし、クライアントはサーバーのハンドシェイク署名を、実際に送信したサポートされる鍵合意のリストと照合するため、不正を検出することができます。
ダウングレード攻撃の問題は、TLS 1.2 では、さらに 複雑になるため、ポスト量子セキュリティをTLS 1.2 に組み込むことに躊躇する理由の1つになっています。
ハンドシェイクのまとめサーバーの応答の最後の部分は、_「server finished」であり、ここまでのすべてのトランスクリプトに関する_メッセージ認証コード (MAC) です。ほとんどの作業はハンドシェイク署名によって行われましたが、セッション再開のようなハンドシェイク署名のないTLSの他の動作モードでは、これは重要となります。
選択したAEADとサーバの共有鍵により、クライアントは共有鍵を計算し、証明書チェーン、ハンドシェイク署名、ハンドシェイクMACを復号・検証することができます。言及していませんでしたが、共有鍵が暗号化に直接使用されることはありません。付け加えますと、共有鍵は、通信のトランスクリプトと一緒に組み合わされて、ハンドシェイクとその後のメイン接続で使用するいくつかの特定の鍵を作成するために使用されます。
ハンドシェイクを終了するために、クライアントは自身のハンドシェイクMACを送信し、その後、ハンドシェイク中に得られた鍵で暗号化されたアプリケーション固有のデータの送信に進むことができます。
Hello! リトライリクエストとは?今描いたのは、クライアントがサーバーがサポートする共有鍵を送信するという望ましい流れです。リトライリクエストでは異なることがあります。もしサーバーがクライアントから宣伝されたどの鍵合意をも受け入れない場合、サーバーはクライアントにそのことを伝え、接続を中断します。
両者がサポートする鍵同意があるものの、クライアントが共有鍵を送信していない場合、サーバーは HelloRetryRequest (HRR) メッセージで応答し、右図のようにクライアントがサポートする特定の鍵合意の共有鍵が要求されます。一方、クライアントは選択された共有鍵とともに、新しい ClientHelloで応答します。
これで終わりではありません。サーバーは、クライアントが共有を送信した鍵合意よりも優先する別の鍵合意を要求するために、_HelloRetryRequest_を送信することも許可されています。例えば、サーバーは、クライアントがポスト量子鍵合意をサポートしているものの、そのための共有鍵を送信していない場合、 _HelloRetryRequest_を送信することができます。
_HelloRetryRequest_は、今日では稀です。ほとんどすべてのサーバーが X25519 鍵合意をサポートし、ほとんどすべてのクライアント (現在 98%) が X25519 共有鍵を送信しています。以前はP-256が事実上の標準であり、長い間、多くのブラウザは HelloRetryRequest を防止するために P-256 と X25519 共有鍵の両方を送信していました。後述しますが、ポスト量子共有鍵を2つ送信する余裕はないかもしれません。
理論的な話TLS 1.3 は、セキュリティやパフォーマンスを犠牲にすることなく、使用する暗号を柔軟に変更できるように設計されており、ポスト量子暗号への移行には好都合です。理論的にはそうなのですが、実際には重大な問題があります。詳しくは後ほど説明します。その前に、当社がデプロイしたポスト量子鍵合意を確認しておきましょう。
デプロイした内容
本日、X25519Kyber512Draft00 および X25519Kyber768Draft00 鍵合意のサポートを、それぞれTLS 識別子 0xfe30 および 0xfe31 を使用して有効にしました。これらは、今年7月に限られた数のゾーンで有効にしたものとまったく同じ鍵合意です。
この2つの鍵合意は、古典的な X25519 と新しいポスト量子 Kyber512 と Kyber768 をそれぞれ、この順番で組み合わせたハイブリッドです。つまり、Kyberが安全でないことが判明しても、接続は X25519 と同じ安全性が保たれます。
Kyberは、今のところ、NISTが標準化として選択した唯一の鍵合意です。KyberはCPUの負荷が非常に軽く、すでに知られている X25519 よりも高速です。その一方で、共有鍵はずっと大きいものです。
.tg {border-collapse:collapse;border-color:#ccc;border-spacing:0;} .tg td{background-color:#fff;border-color:#ccc;border-style:solid;border-width:1px;color:#333; font-family:Arial, sans-serif;font-size:14px;overflow:hidden;padding:10px 5px;word-break:normal;} .tg th{background-color:#f0f0f0;border-color:#ccc;border-style:solid;border-width:1px;color:#333; font-family:Arial, sans-serif;font-size:14px;font-weight:normal;overflow:hidden;padding:10px 5px;word-break:normal;} .tg .tg-c6q4{font-family:inherit;text-align:left;vertical-align:top} .tg .tg-1jcf{font-family:inherit;font-weight:bold;text-align:center;vertical-align:top} .tg .tg-u5z2{font-family:inherit;text-align:center;vertical-align:top} .tg .tg-3xvn{font-family:inherit;font-weight:bold;text-align:left;vertical-align:top} .tg .tg-mpw7{font-family:inherit;text-align:right;vertical-align:top}
共有鍵サイズ(バイト)
Ops/秒(高いほど良い)
アルゴリズム
PQ
Size keyshares(in bytes) | Ops/sec (higher is better) | ||||
---|---|---|---|---|---|
Algorithm | PQ | Client | Server | Client | Server |
Kyber512 | ✅ | 800 | 768 | 50,000 | 100,000 |
Kyber768 | ✅ | 1,184 | 1,088 | 31,000 | 70,000 |
X25519 | ❌ | 32 | 32 | 17,000 | 17,000 |
クライアント
サーバー
クライアント
サーバー
Kyber512
✅
800
768
50,000
100,000
Kyber768
✅
1,184
1,088
31,000
70,000
X25519
❌
32
32
17,000
17,000
X25519とKyberのサイズとCPU性能の比較。性能はハードウェアプラットフォームや実装の制約によって大きく異なるため、あくまで目安として捉えてください。
Kyberは、2024年のNISTによる最終的な標準化までに、マイナーな後方互換性のない変更が行われると予想されています。また、ハイブリッド鍵合意の選択と詳細を含むTLSとの統合は、TLSワーキンググループによってまだ最終化されていません。それが決まれば、速やかに適用していきます。
このため、本日発表された暫定的な鍵同意は長期的にはサポートされず、ベータサービスとして提供されます。pq.cloudflareresearch.com にデプロイに関する最新情報を投稿し、IETF PQC メーリングリストでお知らせします。
TLSネゴシエーションが理論上どのように機能するか、どの鍵同意を追加するかはわかりましたが、なぜ失敗する可能性があるのでしょうか。
実際に問題になりそうな部分
プロトコルの骨化
プロトコルは柔軟性を考慮して設計されることが多いのですが、その柔軟性が実際に発揮されないと、失われることが多くなります。これは_プロトコルの骨化_と呼ばれています。TLS 1.3 の展開が困難だったのは、骨化した例がいくつかあったからです。痛ましい例として、TLSのバージョンネゴシエーションがあります。ClientHello メッセージには、クライアントがサポートする最新バージョンを示す version フィールドがあります。新しいバージョンは TLS 1.3 に割り当てられましたが、テストでは、多くのサーバーが TLS 1.2 に適切にフォールバックせず、代わりに接続をクラッシュさせることが判明しました。骨化にはどう対処できるでしょうか。
ワークアラウンド今日、TLS 1.3は、ClientHello に多くのレガシーフィールドを含めることで、TLS 1.2のように見せかけています。実際のバージョンネゴシエーションは、メッセージの新しい_拡張_に移動されます。TLS 1.2サーバーはこの新しい拡張を無視してTLS 1.2 を継続しますが、TLS 1.3 サーバーはこの拡張を拾ってTLS 1.3 を適切に継続します。
プロトコルのグリースどうすれば骨化を防止できるでしょうか。この経験から、ブラウザは定期的にこの新しいバージョンフィールドでダミーバージョンを宣伝し、誤動作するサーバーを早期に発見できるようにします。これは新しいバージョンフィールドだけでなく、TLSハンドシェイクの他の多くの場所、そして予見的に鍵合意の識別子にも行われています。現在、40%のブラウザが2つのクライアント共有鍵を送信しています。1つは X25519、もう1つは鍵合意の柔軟性を保つための偽の1バイト共有鍵です。
この動作は RFC 8701 で標準化されています。Generate Random Extensions And Sustain Extensibility (GREASE) で、これを私たちはプロトコル_グリーシング_と呼んでいます。アダム・ラングレイ氏のプロトコルの錆びたジョイントには油が必要だという比喩からの「ジョイントにグリースをさす」ということです。
この鍵同意グリースは役に立ちますが、完璧ではありません。この場合、最も懸念されるのは鍵同意共有鍵の大きさだからです。
ClientHelloの分割
ポスト量子鍵同意のサイズは大きく、2つのKyberハイブリッドは832バイトと1,216バイトです。それに比べて、X25519 は32バイトと小さなものです。このような大きな鍵同意を見て、一部の機能で失敗する可能性は低くありません。
最も懸念されるのは、Kyber768ベースの大きい共有鍵です。832バイトの小さなKyber512ベースの共有鍵によるClientHelloは、通常のTCPパケットにギリギリ収まるサイズです。一方、1,216バイトの大きなKyber768共有鍵は、通常、ClientHelloを2つのパケットに分割して送信します。
パケットを組み立てるのは簡単ではありません。部分的なメッセージを周囲に追跡しておく必要があります。通常、これはオペレーティングシステムのTCPスタックによって透過的に行われますが、各パケットを別々に見る最適化されたミドルボックスやロードバランサーは、接続自体を追跡する必要があります (しない場合もあります)。
QUIC
HTTP/3は、QUICに基づいて構築されており、その状況は特に興味深いものです。TCPのようにクライアントが選ぶ単純なポート番号の代わりに、クライアントからのQUICパケットには_接続ID_という、サーバーによって選ばれるものが含まれています。郵便における「あなたの参照番号」と「私たちの参照番号」のようなものだと考えてください。これにより、QUICロードバランサーは、接続を扱う特定のマシンを接続IDにエンコードすることができます。
接続を開くとき、QUICクライアントはサーバーがどの接続IDを希望しているのかわからず、代わりにランダムなものを送信します。大きなClientHelloのように、クライアントが複数の初期パケットを必要とする場合、クライアントは同じランダムな接続IDを使用することになります。QUIC規格では複数の初期パケットが認められていますが、QUICロードバランサーはこれを想定しておらず、基盤となるTCP接続を参照することができないかもしれません。
パフォーマンス
このようなハード障害とは別に、_ソフト_パフォーマンスの低下などの障害も懸念されます。読み込みが遅いと、Webサイトはそもそも切断される可能性があります。
2019年にGoogleとの共同実験で、私たちは2つのポスト量子鍵合意をデプロイしました。NTRU-HRSSをベースにしたCECPQ2と、SIKEをベースにしたCECPQ2bです。NTRU-HRSSはKyberと非常によく似ていますが、少し大きく、遅いです。2019年の結果は、非常に有望なものでした。X25519+NTRU-HRSS (オレンジの線) は、X25519 単体 (青の線) と見分けがつきにくいものです。
私たちは、パフォーマンス、特にテールパフォーマンスに目を光らせていきます。インターネット上で最も速いクライアントから最も遅いクライアントまで、すべての人にとってスムーズな移行を望んでいます。
支援方法
インターネットは非常に異機種な環境にあるシステムです。すべての問題を発見するためには、十分な数の多様なテスターが必要です。これらの鍵同意のサポートを追加するためにブラウザと協業していますが、すべてのネットワークはこれらのブラウザの1つであるとは限りません。
そこで、インターネットを支援するために、あなたのトラフィックの一部をCloudflareドメインに切り替え、これらの新しい鍵合意方式を使用してみてください。当社はBoringSSL、Go、quic-goの方式をオープンソース化しています。BoringSSLとGoについては、こちらのサンプルコードをご覧ください。もし何か問題があれば、ask-research@cloudflare.com までお知らせください。問題点や回避策については、IETF TLSワーキンググループで検討していく予定です。
展望
ポスト量子セキュアインターネットへの移行は急務ですが、課題がないわけではありません。今日、当社はすべてのサーバー (インターネットのかなりの部分) に予備的なポスト量子鍵合意をデプロイし、今日から皆で大規模な移行をテストできるようにしました。2024年、NISTがKyberに弓を引くとき、私たちは皆、ポスト量子インターネットへのスムーズな移行のための土台を築いていることでしょう。
.....
1当社は、HTTP/3を含むTLS 1.3 ベースのプロトコルのみで、これらのポスト量子鍵合意をサポートします。例外として、FIPSモードのWebサイトでは、現時点ではハイブリッド鍵交換を無効にしています。