RFC 8446: TLS 1.3 ハンドシェイクフローの深掘り

Tech

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

RFC 8446: TLS 1.3 ハンドシェイクフローの深掘り

背景

Transport Layer Security (TLS) は、インターネット上で通信のプライバシーとデータ整合性を保証するための不可欠なプロトコルです。TLS 1.2以前のバージョンでは、いくつかの課題が指摘されていました。具体的には、ハンドシェイクに複数のラウンドトリップタイム (RTT) を要することによる接続確立の遅延、レガシーな暗号スイートのサポートによる複雑性の増大と潜在的な脆弱性、そして前方秘匿性 (Forward Secrecy) が一部の場合にしか保証されない点などです。

これらの課題に対処するため、IETF (Internet Engineering Task Force) は新しいバージョルであるTLS 1.3を策定しました。これがRFC 8446として2018年8月に公開されたプロトコルであり、大幅な高速化とセキュリティ強化を実現しています。

設計目標

TLS 1.3は、主に以下の目標を掲げて設計されました。

  • 高速化:

    • ハンドシェイクに必要なRTTを削減し、接続確立時間を短縮します。特に、多くの場合で1-RTTハンドシェイクを可能にし、再開時には0-RTTを実現します。
  • セキュリティ強化:

    • 前方秘匿性 (Forward Secrecy) をすべての鍵交換で強制し、長期鍵が漏洩しても過去のセッションが解読されるのを防ぎます。

    • 脆弱な暗号スイートや機能を削除し、プロトコルの攻撃対象領域を最小化します。

    • ハンドシェイクメッセージの大部分を暗号化することで、中間者攻撃に対する耐性を高めます。

  • 複雑性の軽減:

    • 不要な暗号スイートや拡張機能を削除し、プロトコルの実装と分析を簡素化します。

詳細

TLS 1.3 Full Handshakeフロー

TLS 1.3のFull Handshakeは、既存のTLS 1.2と比較して大幅に簡素化され、多くの場合で1-RTTでの鍵確立を可能にします。クライアントはClientHelloメッセージで鍵共有候補とサポートする暗号スイートを提示し、サーバーはそれらの中から選択してServerHelloを返します。以降のメッセージの大部分は暗号化されます。

sequenceDiagram
    participant Client
    participant Server

    Client ->> Server: ClientHello (Key Share, Cipher Suites, etc.)
    activate Server
    Server ->> Client: ServerHello (Selected Key Share, Cipher Suite)
    Server ->> Client: EncryptedExtensions
    alt Server Certificate
        Server ->> Client: Certificate
        Server ->> Client: CertificateVerify
    end
    Server ->> Client: Server Finished
    deactivate Server
    activate Client
    Client ->> Server: Client Finished
    deactivate Client
    Client> Server: Application Data (TLS Record Protocol)
  1. ClientHello: クライアントはサポートするTLSバージョン (1.3のみ)、暗号スイート候補、鍵共有メカニズム (例: ECDHE) のパラメータ、ランダムなバイト列、および拡張を送信します。

  2. ServerHello: サーバーはクライアントの選択肢の中から、合意した暗号スイート、選択された鍵共有パラメータ、ランダムなバイト列、および拡張を返します。この時点で、両者は共有秘密鍵を導出できます。

  3. EncryptedExtensions: サーバーは、暗号化された拡張情報を送信します。これはTLS 1.2のServerHello後の多くの拡張に代わるものです。

  4. Certificate / CertificateVerify (オプション): サーバーが認証に証明書を使用する場合、証明書と、ハンドシェイクのトランスクリプトに対する署名を送信します。

  5. Server Finished: サーバーは、これまでのハンドシェイクメッセージのハッシュに対するMAC (Message Authentication Code) を送信し、自身の鍵確立とハンドシェイク完了を示します。

  6. Client Finished: クライアントも同様にMACを送信し、自身のハンドシェイク完了を示します。

  7. Application Data: 以降、暗号化されたアプリケーションデータの交換が開始されます。

TLS 1.3 0-RTT Handshakeフロー

TLS 1.3では、過去のセッション情報 (PSK: Pre-shared Key) を利用して、0-RTT (ゼロ・ラウンドトリップ・タイム) で早期にアプリケーションデータを送信する機能が導入されました。これにより、TCP接続確立後にさらに1-RTTを待つことなく、最初のクライアントリクエストを送信できるようになります。

sequenceDiagram
    participant Client
    participant Server

    Client ->> Server: ClientHello (PSK Identity, early_data extension, early Application Data)
    activate Server
    Server ->> Client: ServerHello (Selected PSK Identity)
    Server ->> Client: EncryptedExtensions
    alt Server Certificate (if not using PSK-only)
        Server ->> Client: Certificate
        Server ->> Client: CertificateVerify
    end
    Server ->> Client: Server Finished
    deactivate Server
    activate Client
    Client ->> Server: Client Finished
    deactivate Client
    Client> Server: Application Data (TLS Record Protocol)
  1. ClientHello with PSK and Early Data: クライアントは、前回のセッションで取得したPSK識別子を含んだClientHelloを送信し、同時に0-RTTで暗号化されたアプリケーションデータ (Early Data) を送信します。

  2. ServerHello with PSK: サーバーはPSK識別子を選択し、通常のハンドシェイクと同様の残りのメッセージを送信します。

  3. Application Data: 0-RTTデータに加えて、残りのアプリケーションデータも交換されます。

TLS 1.3 レコード層構造

TLS 1.3のレコード層は、TLSPlaintextとTLSCiphertextの2つの形式でデータをカプセル化します。

// TLSPlaintext (ハンドシェイクメッセージ、アラート、アプリケーションデータ)
Content Type:8          // データタイプ (例: handshake, alert, application_data)
Legacy Record Version:16 // TLS 1.3実装が生成する全てのレコードで 0x0303 (TLS 1.2)
Length:16               // フラグメントの長さ
Fragment:variable       // 実際のペイロード

// TLSCiphertext (暗号化されたレコード)
Opaque Type:8           // 常に 0x17 (application_data)
Legacy Record Version:16 // TLS 1.3実装が生成する全てのレコードで 0x0301 (TLS 1.0)
Length:16               // encrypted_recordの長さ
Encrypted Record:variable // AEAD暗号化データ + MAC + オリジナルのContent Type + パディング

鍵スケジュール

TLS 1.3では、鍵導出関数 (KDF) としてHMAC-based Key Derivation Function (HKDF) を使用し、Diffie-Hellman (DH) またはElliptic Curve Diffie-Hellman (ECDH) で確立された共有秘密から、セッション全体の鍵を安全に導出します。

flowchart TD
    A["DHE/ECDHE Shared Secret"] --> B{"HKDF-Extract: Initial Secret"}
    B --> C["Handshake Secret"]
    C --> D{"HKDF-Expand: Handshake Traffic Secret"}
    D --> E["Client Handshake Traffic Secret"]
    D --> F["Server Handshake Traffic Secret"]
    F --> G{"HKDF-Expand: Application Traffic Secret"}
    G --> H["Client Application Traffic Secret"]
    G --> I["Server Application Traffic Secret"]
    I --> J["Resumption Master Secret(\"for 0-RTT\")"]

この鍵スケジュールにより、複数の段階で鍵が導出され、各段階の鍵が次の段階の導出に影響を与えることで、鍵の安全性が高まります。

相互運用

TLS 1.3は、既存のプロトコルスタックに大きな影響を与えます。

  • TLS 1.2 との比較:

    • RTT: TLS 1.2はFull Handshakeで2-RTTを要したのに対し、TLS 1.3は1-RTT、再開時は0-RTTに短縮されます。

    • 暗号スイート: TLS 1.3では、前方秘匿性を強制するより安全なAEAD (Authenticated Encryption with Associated Data) 暗号スイートのみがサポートされます。

    • ハンドシェイクメッセージの暗号化: TLS 1.3では、ServerHello以降の多くのハンドシェイクメッセージが暗号化され、傍受者からの情報漏洩を防ぎます。

    • バージョンネゴシエーション: 古いTLSクライアントとの互換性のため、TLS 1.3はTLS 1.2互換のClientHello構造を使用し、拡張を介してバージョン1.3を通知します。

  • HTTP/2 (TLS 1.3) と HTTP/3 (QUIC/TLS 1.3) との比較:

    • HTTP/2: TCP上でTLS 1.3を使用します。TLS 1.3は高速化に貢献しますが、TCP自体のHead-of-Line (HOL) Blocking問題は残ります。複数のHTTPストリームが単一のTCP接続を共有するため、パケットロスが発生すると全てのストリームがブロックされる可能性があります。

    • HTTP/3: UDP上でQUICプロトコルを使用し、その暗号化層としてTLS 1.3を統合しています。QUICは多重化されたストリームをサポートし、プロトコルレベルでHOL Blockingを回避します。これにより、単一のストリームでパケットロスが発生しても、他のストリームの処理は継続されます。

セキュリティ考慮

TLS 1.3はセキュリティを大幅に強化しましたが、特に0-RTT機能には注意が必要です。

  • リプレイ攻撃 (Replay Attacks): 0-RTTで送信される早期データは、クライアントがClient Finishedメッセージを送信するまで認証されていません。このため、悪意のある攻撃者がこの早期データを傍受し、サーバーに再送することで、冪等性 (idempotent) のない操作を繰り返し実行させるリプレイ攻撃のリスクがあります。サーバーは、ノンスやタイムスタンプを利用して早期データの重複を検出・拒否する必要があります。

  • ダウングレード攻撃 (Downgrade Attacks): TLS 1.3は、古いTLSバージョンへの意図的なダウングレード攻撃を防ぐためのメカニズムを含んでいます。具体的には、ClientHelloにダウングレード検出用のシグナルを含めることで、中間者攻撃者がプロトコルバージョンを不正にダウングレードしようとした場合にこれを検知し、接続を終了させます。

  • キー更新 (Key Updates): 長時間継続する接続における前方秘匿性を強化するため、TLS 1.3はハンドシェイク後にも鍵を更新するPost-Handshake Key Updateメカニズムをサポートしています。これにより、特定の鍵が漏洩した場合のリスク期間を短縮できます。

  • 0-RTTの再送リスク: 前述のリプレイ攻撃と関連しますが、0-RTTデータは、サーバーによって認証される前にネットワーク上で傍受される可能性があります。そのため、冪等でない操作(例: 決済処理)には0-RTTデータを使用しないことがRFC 8446で強く推奨されています。

実装メモ

TLS 1.3の実装には、ネットワーク層の特性を考慮する必要があります。

  • MTU / Path MTU: TLSレコードはフラグメント化と再構成の対象となります。特にQUIC/HTTP/3のようなUDPベースのプロトコルでは、Path MTU Discovery (PMTUD) が重要です。適切なPMTUの検出とそれに応じたレコードサイズの調整は、フラグメンテーションによる性能劣化やパケットロスを避けるために不可欠です。

  • HOL blocking回避: TCPベースのTLS 1.3では、基盤となるTCPのHOL blocking問題は残ります。HTTP/2はTCPの上で多重化しますが、下層のTCPが原因で依然としてHOL blockingが発生します。これに対し、HTTP/3はQUIC上でTLS 1.3を実装することで、プロトコルレベルでHOL blockingを回避しています。

  • キュー制御: サーバーおよびクライアントの両方で、ハンドシェイクメッセージやアプリケーションデータの送受信キューを適切に制御することが、遅延やスループットに直接影響します。特にトラフィックが多い環境では、適切なバッファ管理と輻輳制御戦略が必要です。

  • 優先度: HTTP/2やHTTP/3では、リソースの優先度付けが可能です。TLSレイヤーでは、ハンドシェイクメッセージや、HTTPレイヤーからの高優先度ストリームに対応するTLSレコードに対して、適切な優先度付けとスケジューリングを行うことが、応答性能の向上に繋がります。

まとめ

RFC 8446によって定義されたTLS 1.3は、インターネット通信のセキュリティと性能を大幅に向上させる重要なプロトコルです。1-RTTハンドシェイクと0-RTT再開による高速化、強化された前方秘匿性と簡素化された暗号スイートによるセキュリティ向上は、現代のインターネット要件に合致しています。特にHTTP/3と組み合わせることで、従来のプロトコルスタックの制約を打破し、より効率的でセキュアな通信環境を提供します。実装にあたっては、リプレイ攻撃対策やMTU/HOL blockingなどのネットワーク層の特性への深い理解と適切な対応が不可欠です。

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

コメント

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