RFC 8446: TLS 1.3 鍵交換プロセスの詳細

Tech

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

RFC 8446: TLS 1.3 鍵交換プロセスの詳細

背景

Transport Layer Security (TLS) は、インターネット上で安全な通信を確立するための暗号化プロトコルです。その最新バージョンであるTLS 1.3は、RFC 8446として2018年8月にIETFによって標準化されました。TLS 1.2以前のバージョンが抱えていたいくつかの課題、特にハンドシェイクの遅延とセキュリティの複雑性を解消するために設計されました。

TLS 1.2では、フルハンドシェイクに2回のラウンドトリップタイム (2-RTT) が必要であり、これはWebページのロード時間やAPI呼び出しのレイテンシに直接影響していました。また、古い暗号スイートや鍵交換メカニズム(特にRSA鍵交換)のサポートが残っており、これによりプロトコル実装が複雑になり、潜在的なセキュリティリスクが増大していました。

設計目標

TLS 1.3 (RFC 8446) は、以下の主要な設計目標を掲げています。

  1. ハンドシェイクの高速化: ほとんどのハンドシェイクを1-RTTに短縮し、条件によっては0-RTTでアプリケーションデータの送信を開始できるようにすることで、接続確立のレイテンシを大幅に削減します。

  2. セキュリティの強化:

    • Perfect Forward Secrecy (PFS) を強制します。これにより、長期秘密鍵が侵害されても、過去のセッション鍵が解読されることを防ぎます。

    • 古い、または脆弱な暗号スイート(例:RC4, SHA1, CBCモードのAEADではない暗号)を完全に廃止し、より堅牢な認証付き暗号化 (AEAD) を強制します。

    • 鍵交換メカニズムを(Elliptic Curve) Diffie-Hellman ephemeral ((EC)DHE) またはPre-Shared Key (PSK) に限定し、RSA鍵交換を削除します。

  3. プロトコルの簡素化: プロトコルをより理解しやすく、実装しやすくするために、多くのオプションや設定を削除または合理化します。これにより、設定ミスによるセキュリティ脆弱性のリスクを低減します。

  4. ダウングレード攻撃からの保護: 過去のTLSバージョンへの意図的なダウングレード攻撃を防ぐためのメカニズムを組み込みます。

詳細

TLS 1.3の鍵交換プロセスは、これらの設計目標を達成するために大幅に刷新されました。主要な変更点として、Diffie-Hellman鍵交換の強制、鍵導出関数のHKDFへの統一、そして0-RTTハンドシェイクの導入が挙げられます。

鍵交換プロセスの概要

TLS 1.3の鍵交換プロセスは、主にDiffie-Hellman鍵交換(楕円曲線Diffie-Hellman鍵交換を含む)または事前共有鍵 (PSK) に基づいています。クライアントとサーバーは、これらのメカニズムを通じて共有の秘密鍵を導出し、その後の通信の暗号化に使用します。

flowchart TD
    A[ClientHello] --> B{"Key Share Negotiation"};
    B -- ECDHE/DHE Key Share --> C["鍵導出 (ハンドシェイク秘密鍵)"];
    B -- PSK Identity --> D["鍵導出 (PSK秘密鍵)"];
    C --> E["ServerHello, EncryptedExtensions"];
    D --> E;
    E --> F{"認証"};
    F -- 証明書 + 検証 --> G["Finishedメッセージ"];
    F -- PSKのみ --> G;
    G --> H["アプリケーション通信秘密鍵"];
    H --> I["アプリケーションデータ交換"];
    I --> J{"鍵更新?"};
    J -- はい --> K["新しいアプリケーション通信秘密鍵"];
    J -- いいえ --> I;

根拠[1]

1-RTTハンドシェイク

TLS 1.3の標準的なハンドシェイクは、フルハンドシェイクを1-RTTで完了させることができます。クライアントは ClientHello メッセージでDiffie-Hellman鍵共有の公開鍵を提示し、サーバーは最初の応答で自身の公開鍵と、以降の通信を暗号化するための情報を提供します。

sequenceDiagram
    participant C as クライアント
    participant S as サーバー
    C ->> S: ClientHello |KeyShare, SupportedVersions, cipher_suites, extensions|
    S ->> C: ServerHello |選択されたCipherSuite, KeyShare|
    activate S
    S ->> C: EncryptedExtensions |ALPN, MaxEarlyDataSize|
    S ->> C: Certificate |サーバー証明書 (必要であれば)|
    S ->> C: CertificateVerify |ハンドシェイクメッセージの署名|
    S ->> C: Finished |ハンドシェイクメッセージのハッシュ|
    deactivate S
    Note over C,S: 鍵確立 (1-RTT)
    C ->> S: Finished |ハンドシェイクメッセージのハッシュ|
    activate C
    C ->> S: アプリケーションデータ
    deactivate C
    S ->> C: アプリケーションデータ

根拠[1]

0-RTTハンドシェイク

TLS 1.3の最も画期的な機能の一つが0-RTTハンドシェイクです。これは、以前のセッションで確立された事前共有鍵 (PSK) を利用して、クライアントが最初のメッセージ(ClientHello)と共に暗号化されたアプリケーションデータを送信できる機能です。これにより、接続確立のためのRTTをゼロにすることができ、特にレイテンシに敏感なアプリケーションで大きなパフォーマンス向上が期待できます。

sequenceDiagram
    participant C as クライアント
    participant S as サーバー
    Note over C,S: 以前の接続でPSKを確立済み
    C ->> S: ClientHello |PSK, KeyShare, early_data_indication|
    C ->> S: Early Application Data |PSK + クライアントの鍵共有で保護|
    activate S
    S ->> C: ServerHello |選択されたCipherSuite, KeyShare|
    S ->> C: EncryptedExtensions |ALPN, MaxEarlyDataSize|
    S ->> C: Certificate |サーバー証明書 (必要であれば)|
    S ->> C: CertificateVerify |ハンドシェイクメッセージの署名|
    S ->> C: Finished |ハンドシェイクメッセージのハッシュ|
    deactivate S
    Note over C,S: 鍵確立 (Early Dataは0-RTT)
    C ->> S: Finished |ハンドシェイクメッセージのハッシュ|
    activate C
    C ->> S: アプリケーションデータ
    deactivate C
    S ->> C: アプリケーションデータ

根拠[1]

鍵導出

TLS 1.3では、すべての鍵導出にHKDF (HMAC-based Key Derivation Function) を使用します。これにより、鍵導出プロセスが統一され、安全性と簡潔性が向上しました。HKDFは、初期の秘密鍵からハンドシェイク鍵、アプリケーション鍵など、様々な種類の鍵を段階的に導出するために利用されます。

ClientHelloメッセージ構造(簡略化)

TLS 1.3の ClientHello メッセージは、従来のTLSバージョンとは異なり、主要なパラメータを拡張として含みます。

ClientHello Message Structure (Simplified)
version:2 (legacy_record_version = 0x0301) - 互換性のため常に0x0301
random:32 (client_random)
  downgrade_protection_marker:8 (特定のバイトシーケンスでダウングレード検出)
legacy_session_id:Variable (0-32 bytes) - 空にすることが推奨
cipher_suites_length:2
cipher_suites:Variable (2バイトのcipher suiteコードのリスト)
  cipher_suite:2 (例: TLS_AES_128_GCM_SHA256)
extensions_length:2
extensions:Variable (拡張のリスト)
  extension_type:2 (拡張の種類)
  extension_data_length:2 (拡張データの長さ)
  extension_data:Variable (拡張データ本体)
    supported_versions:Variable (TLS 1.3を示す0x0304を含む)
    key_share:Variable (KeyShareEntryのリスト)
      named_group:2 (例: x25519, secp256r1)
      key_exchange:Variable (公開鍵)
    psk_key_exchange_modes:Variable (PSKの使用モード、例: PSK_DHE_KE)
    pre_shared_key:Variable (PSKIdentityのリスト)

根拠[1]

相互運用性

TLS 1.3は、古いTLSバージョンとの後方互換性を考慮しつつも、セキュリティとパフォーマンスの改善を優先しています。

  • ダウングレード保護: ClientHello および ServerHello メッセージの random フィールドに、TLS 1.3へのダウングレード試行を検出するための特定のバイトシーケンス (例: 0x44 0x4F 0x57 0x4E 0x47 0x52 0x44) が含まれます。これにより、中間者攻撃による古いバージョンへの強制ダウングレードを防ぎます。

  • 既存TLSバージョンとの共存: TLS 1.3対応クライアントは、ClientHellosupported_versions 拡張でサポートする全てのバージョンを提示します。サーバーは、クライアントと自身がサポートする最も新しいバージョンを選択します。

  • HTTP/2とHTTP/3 (QUIC) との関係:

    • HTTP/2: TLS 1.2またはTLS 1.3をトランスポート層としてTCP上で動作します。TLS 1.3の導入により、ハンドシェイクのレイテンシ削減の恩恵を受けます。

    • HTTP/3: QUICプロトコル上で動作し、QUICはTLS 1.3をそのセキュリティ層として必須としています。QUICとTLS 1.3の組み合わせは、TCPの持つHOL (Head-of-Line) Blocking問題を回避し、さらに効果的な0-RTT接続を可能にすることで、大幅なパフォーマンス向上を実現します。

既存プロトコルとの比較(TLS 1.2 vs TLS 1.3)

特徴 TLS 1.2 TLS 1.3 (RFC 8446)
フルハンドシェイク 2-RTT 1-RTT
セッション再開 1-RTT (Session ID/Ticket) 0-RTT/1-RTT (PSK)
鍵交換 RSA, DHE, ECDHE DHE, ECDHE, PSK のみ
Perfect Forward Secrecy オプション (DHE/ECDHE選択時) 強制 (DHE/ECDHEまたはPSK+DHE/ECDHE)
暗号スイート 多くのレガシー暗号 (RC4, SHA1, CBCモード) を含む AEAD (AES-GCM, ChaCha20-Poly1305) のみ
鍵導出関数 PRF (Pseudo-Random Function) HKDF (HMAC-based Key Derivation Function) のみ
初期アプリケーションデータ ハンドシェイク完了後 0-RTT対応の場合、ClientHelloと共に送信可能
ハンドシェイクの暗号化 一部 (ChangeCipherSpec以降) ServerHello 以降のすべてのハンドシェイクメッセージ

セキュリティ考慮事項

TLS 1.3はセキュリティを大幅に強化していますが、特定の側面では注意が必要です。

  • リプレイアタック (0-RTT): 0-RTTデータは、サーバーがクライアントを認証する前に送信されるため、潜在的にリプレイ攻撃の対象となります。RFC 8446は、サーバーが冪等でない0-RTTデータを処理する際には、リプレイ対策(例: ノンス、セッションチケットの使い捨て)を講じるよう義務付けています。クライアントは、early_data_indication 拡張で0-RTTデータがリプレイ可能であるかどうかを示すことができますが、サーバー側での適切な処理が不可欠です。

  • ダウングレード攻撃: TLS 1.3は、ClientHelloServerHellorandom フィールドに特定のマーカーを含めることで、プロトコルのダウングレード攻撃を検出し、防止するメカニズムを備えています。

  • 鍵更新 (Key Update): 長時間存続するTLSセッションにおいて、鍵の漏洩リスクを低減するため、TLS 1.3ではハンドシェイク後に新しい鍵を生成・交換する「鍵更新」機能が提供されます。クライアントまたはサーバーが KeyUpdate メッセージを送信することで、セッション中に新しいアプリケーションデータ保護鍵を確立できます。

  • Perfect Forward Secrecy (PFS) の強制: TLS 1.3は、ECDHEまたはDHE鍵交換を強制することでPFSを常に保証します。これにより、たとえサーバーの長期的な秘密鍵が将来的に漏洩しても、過去の通信内容は保護されます。

  • 秘密鍵の乱数性: 鍵交換に使用される乱数生成器の品質は、プロトコル全体のセキュリティに直結します。暗号学的に安全な乱数生成器 (CSPRNG) の利用が不可欠です。

実装メモ

TLS 1.3を実装または展開する際には、以下の点に留意する必要があります。

  • MTU / Path MTU: TLS 1.3のレコード層は、基盤となるトランスポート層(特にUDP上のQUICなど)のMTU内に収まる必要があります。フラグメンテーションはパフォーマンス低下やパケットロスにつながるため、Path MTU Discovery (PMTUD) の実施が重要です。

  • HOL blocking 回避: TCP上でTLS 1.3を使用する場合、TCPの特性上、パケットロスが発生するとTCPストリーム全体がブロックされるHOL blockingの問題は残ります。HTTP/3でTLS 1.3が使用されるQUICプロトコルでは、UDP上で独自のストリーム多重化と信頼性メカニズムを実装することで、HOL blockingを効果的に回避しています。

  • キュー制御と優先度: 特に0-RTTデータを使用する場合、アプリケーションデータの重要性に基づいてキュー制御や優先度付けを適切に行う必要があります。リプレイ攻撃のリスクを考慮し、重要度の低いデータや冪等な操作に0-RTTを限定するなどの戦略が有効です。

  • 中間ボックスの互換性: レガシーなネットワーク中間ボックス(ファイアウォール、ロードバランサーなど)がTLS 1.3を正しく処理できない場合があります。TLS 1.3は、ClientHellolegacy_record_version フィールドを 0x0301 (TLS 1.0) に設定するなど、中間ボックスが古いTLSバージョンと誤認するような工夫がされていますが、一部で問題が発生する可能性があります。

まとめ

RFC 8446で定義されるTLS 1.3は、インターネット通信のセキュリティとパフォーマンスを大幅に向上させた重要な進化です。1-RTTハンドシェイクによる高速な接続確立、0-RTTデータによるさらなるレイテンシ削減は、WebアプリケーションやAPI通信の応答性向上に貢献します。

また、Perfect Forward Secrecyの強制、古い暗号スイートの廃止、鍵導出のHKDFへの統一など、セキュリティ面での強化も多岐にわたります。一方で、0-RTTの採用にはリプレイ攻撃への対策が必須であり、実装者はセキュリティ上の考慮事項を十分に理解し、適切に対処する必要があります。今後もTLS 1.3は、HTTP/3を支える基盤技術として、安全で高速なインターネットの実現に不可欠な役割を担い続けるでしょう。

根拠: [1] IETF, “RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3”, 2018年8月, https://datatracker.ietf.org/doc/html/rfc8446

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

コメント

タイトルとURLをコピーしました