TLS 1.3 (RFC 8446)における鍵交換と安全性

Tech

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

TLS 1.3 (RFC 8446)における鍵交換と安全性

背景

Transport Layer Security (TLS) は、インターネット上で安全な通信を確立するための暗号化プロトコルです。その前身であるSecure Sockets Layer (SSL) から進化し、ウェブブラウジング、電子メール、VoIPなど、多岐にわたるアプリケーションで利用されています。TLS 1.2は長らく標準として利用されてきましたが、時間の経過と共に、いくつかの設計上の複雑性、旧来の暗号スイートのサポート、そしてパフォーマンスの制約が浮上してきました。例えば、ハンドシェイクのオーバーヘッドが大きく、特にモバイル環境でのレイテンシが問題となることがありました。

こうした課題に対応するため、2018年8月にRFC 8446としてTLS 1.3が公開されました。この新しいバージョンは、より堅牢なセキュリティ、簡素化されたプロトコル、そして大幅なパフォーマンス向上を実現することを目標としています。

設計目標

TLS 1.3の主な設計目標は以下の通りです。

  1. セキュリティの強化: 過去のバージョンで利用可能だった脆弱な暗号スイートや機能を廃止し、前方秘匿性 (Perfect Forward Secrecy; PFS) を強制することで、通信の機密性と完全性を高めます。

  2. プロトコルの簡素化: ハンドシェイクプロセスを合理化し、特に鍵交換の仕組みをより明確で、エラーが発生しにくいものにします。これにより、実装の複雑さを軽減し、潜在的な脆弱性を減少させます。

  3. パフォーマンスの向上: ハンドシェイクのラウンドトリップ回数 (RTT) を削減し、場合によっては0-RTTでデータ転送を開始できるようにすることで、接続確立にかかる時間を短縮し、全体的なユーザーエクスペリエンスを改善します。

  4. プライバシーの向上: ハンドシェイクの一部を暗号化することで、通信内容だけでなく、利用されている証明書チェーンなどのメタデータの漏洩を防ぎ、ユーザーのプライバシーを保護します。

詳細

鍵交換メカニズム

TLS 1.3では、鍵交換メカニズムが大幅に強化され、前方秘匿性 (PFS) の保証が必須となりました。これは、セッション鍵が長期的な秘密鍵から独立して導出されるため、もしサーバーの秘密鍵が将来漏洩しても、過去の通信内容は解読されないことを意味します。

  • Diffie-Hellman鍵交換の強制:

    • TLS 1.3では、すべての鍵交換において一時的なDiffie-Hellman (DHE) または楕円曲線Diffie-Hellman (ECDHE)の使用が必須です [1, Sec 1]。これにより、PFSが自動的に提供されます。TLS 1.2でサポートされていたRSA鍵転送(長期的なRSA秘密鍵が漏洩した場合に過去の通信が解読されるリスクがある)は廃止されました。
  • HKDF (HMAC-based Key Derivation Function):

    • すべての鍵導出は、HKDFに基づいて行われます [1, Sec 7.1]。この関数は、ハンドシェイク中に交換されるDiffie-Hellman共有シークレットから、トラフィック鍵、初期化ベクトル (IV)、およびその他の必要な鍵材料を効率的かつセキュアに導出するために使用されます。HKDFの採用により、鍵導出プロセスが統一され、簡素化されました。
  • PSK (Pre-Shared Key) の統合:

    • 事前共有鍵 (PSK) は、再開セッションや外部の認証情報(例えばOAuthトークン)に基づいて鍵交換を行うために使用されます。PSKは、ECDHE/DHEと組み合わせて使用されることもあり、より強力な鍵確立と認証を提供します [1, Sec 2]。

ハンドシェイクプロトコル

TLS 1.3のハンドシェイクは、TLS 1.2と比較して大幅に簡素化され、パフォーマンスが向上しました。

完全ハンドシェイク (1-RTT)

通常のハンドシェイクは、ほとんどのケースで1ラウンドトリップタイム (1-RTT) で完了します。これはTLS 1.2の2-RTTと比べて大きな改善です。

sequenceDiagram
    actor Client
    participant Server

    Client ->> Server: ClientHello (|KeyShare|, |SupportedVersions|, |SupportedGroups|)
    Server ->> Client: ServerHello (|SelectedVersion|, |SelectedGroup|, |KeyShare|)
    Server ->> Client: ChangeCipherSpec (Optional)
    Server ->> Client: EncryptedExtensions
    Server ->> Client: Certificate (|If using certificate-based authentication|)
    Server ->> Client: CertificateVerify
    Server ->> Client: Finished
    Client ->> Server: ChangeCipherSpec (Optional)
    Client ->> Server: Finished
    Client Server: |Application Data (Encrypted with traffic keys)|

解説:

  1. ClientHello: クライアントは、サポートするTLSバージョン、暗号スイート、鍵共有パラメーター (KeyShare) などを送信します [1, Sec 4.1.2]。鍵共有パラメーターは、Diffie-Hellman鍵交換に必要な公開鍵の一部を事前に含みます。

  2. ServerHello: サーバーは、選択したTLSバージョン、暗号スイート、鍵共有パラメーターを応答します [1, Sec 4.2]。これにより、クライアントとサーバーは共有シークレットを独立して計算できます。

  3. EncryptedExtensions: サーバーは、アプリケーション層のプロトコルネゴシエーション (ALPN) など、暗号化された拡張情報を送信します [1, Sec 4.3.1]。

  4. Certificate/CertificateVerify: サーバーがクライアントに自身を認証する必要がある場合、証明書とその検証メッセージを送信します [1, Sec 4.3.2, 4.3.3]。これらのメッセージは暗号化されています。

  5. Finished: 両者が導出した鍵を用いて、ハンドシェイクの完全性と認証を検証するためのハッシュ値(Finishedメッセージ)を交換します [1, Sec 4.4]。これが成功すると、以降の通信は確立されたトラフィック鍵で暗号化されます。

0-RTTハンドシェイク

以前のセッション情報(PSK)を再利用することで、初回リクエスト時にアプリケーションデータを送信できる「0-RTT (Zero Round-Trip Time) ハンドシェイク」が可能です。これにより、ほとんどの接続で追加のRTTを待つことなくデータ転送を開始できます。

sequenceDiagram
    actor Client
    participant Server

    Client ->> Server: ClientHello (|KeyShare|, |SupportedVersions|, |PSK|, |early_data|)
    Server -->> Client: |(Decrypts early_data if PSK valid, applies anti-replay)|
    Server ->> Client: ServerHello (|SelectedVersion|, |SelectedGroup|, |KeyShare|, |PSK|)
    Server ->> Client: ChangeCipherSpec (Optional)
    Server ->> Client: EncryptedExtensions
    Server ->> Client: Certificate (|If needed|)
    Server ->> Client: CertificateVerify
    Server ->> Client: Finished
    Client ->> Server: ChangeCipherSpec (Optional)
    Client ->> Server: Finished
    Client Server: |Application Data (Encrypted with traffic keys)|

解説:

  1. ClientHello (with early_data): クライアントは、以前のセッションから取得したPSKと、アプリケーションデータ (early_data) を含むClientHelloを送信します。

  2. サーバー処理: サーバーはPSKを検証し、早期データを復号化して処理を開始します。この際、リプレイ攻撃防止策が適用されます。

  3. 通常のハンドシェイクの完了: その後、通常の1-RTTハンドシェイクが進行し、新しいセッション鍵が確立されます。

プロトコル構造

TLS 1.3のプロトコルは、下位レイヤーから上位レイヤーへ、TLSレコード層、ハンドシェイクプロトコル、アラートプロトコル、アプリケーションデータプロトコルという階層構造を持ちます。ここでは、TLSレコード層とハンドシェイクメッセージの基本的な構造を示します。

TLSレコード層ヘッダ

すべてのTLSデータはレコードとしてカプセル化されます [1, Sec 5]。

ContentType:8 (e.g., handshake, application_data, alert)
LegacyProtocolVersion:16 (0x0301, for backward compatibility; actual version is negotiated in handshake)
Length:16 (length of the fragment, in bytes)
Fragment:... (encrypted handshake, application data, or alert message)

TLS 1.3では、LegacyProtocolVersionは常に0x0301 (TLS 1.0) を使用し、実際のバージョンネゴシエーションはハンドシェイク内の拡張で行われます。これにより、TLS 1.3非対応の中間ボックスを通過しやすくなります。

TLSハンドシェイクメッセージヘッダ

ハンドシェイクプロトコルは、安全な通信チャネルを確立するために使用されるメッセージで構成されます [1, Sec 4]。

MsgType:8 (e.g., ClientHello, ServerHello, EncryptedExtensions, Finished)
Length:24 (length of the message content, in bytes)
Body:... (message-specific content)

TLS 1.3では、ServerHello以降の多くのハンドシェイクメッセージが、最初の鍵交換で確立された鍵によって暗号化されます。これにより、ハンドシェイク中の情報漏洩が大幅に減少します。

既存プロトコルとの比較

TLS 1.3は、TLS 1.2以前のバージョンや、上位プロトコルであるHTTP/2やHTTP/3 (QUIC) との関連で、その特徴が際立ちます。

  • TLS 1.2 と TLS 1.3:

    • ハンドシェイク:

      • TLS 1.2: 通常2-RTT。セッション再開も1-RTTを要する場合が多い。

      • TLS 1.3: 通常1-RTT。0-RTTでデータ転送開始が可能。

    • 鍵交換:

      • TLS 1.2: RSA鍵転送をサポート(PFSなし)。DHE/ECDHEは任意。

      • TLS 1.3: DHE/ECDHEが必須(PFS強制) [1, Sec 1]。RSA鍵転送は廃止。

    • 暗号スイート:

      • TLS 1.2: 多数の暗号スイートをサポートするが、脆弱なもの(RC4, SHA-1, 3DES, AES-CBCなど)も含まれる。

      • TLS 1.3: 強固なAEAD (Authenticated Encryption with Associated Data) 暗号(AES-GCM, CHACHA20-POLY1305など)のみをサポート [1, Appx B]。

    • ハンドシェイクの可視性:

      • TLS 1.2: 証明書チェーンなど、ハンドシェイクの多くの部分が平文で送信される。

      • TLS 1.3: ServerHello以降のハンドシェイクメッセージの大部分が暗号化されるため、プライバシーが向上 [1, Sec 1]。

    • セッション再開:

      • TLS 1.2: Session IDやSession Ticketを使用し、複雑なメカニズム。

      • TLS 1.3: PSKを基本とし、NewSessionTicketメッセージでシンプルに実現 [1, Sec 4.6.1]。

  • TLS 1.3とHTTP/3 (QUIC):

    • TLS 1.3は、HTTP/3の基盤となるQUICプロトコルのセキュリティ層として設計されました。QUICはTCPのヘッドオブラインブロッキング (HOL blocking) 問題を解決するために複数のストリームを多重化しますが、その安全な通信路確立にTLS 1.3が利用されます。

    • TLS 1.3の1-RTT/0-RTTハンドシェイクは、QUICの低レイテンシ設計と相性が良く、HTTP/3のパフォーマンス向上に大きく貢献しています。QUICは独自の接続IDを持つため、IPアドレスやポート番号の変更による再接続時にTLSハンドシェイクのオーバーヘッドを避けることができます。

相互運用性

TLS 1.3は、従来のTLSバージョンとの後方互換性を考慮しつつも、セキュリティ強化のために一部の古い機能を大胆に削除しています。

  • ダウングレード攻撃への対策:

    • TLS 1.3は、意図しない、または悪意のあるダウングレード攻撃を防ぐためのメカニズムを組み込んでいます。ClientHelloメッセージの乱数フィールドには、TLS 1.3をサポートしていることを示す特別なダウングレード保護シグナルが含まれます [1, Sec 4.1.2]。もしTLS 1.3対応サーバーがこのシグナルを持つClientHelloを受け取り、かつ、TLS 1.2以下のバージョンでハンドシェイクを完了した場合、ダウングレード攻撃を検出し、接続を終了します。
  • 拡張性 (Extensions):

    • TLS 1.3は、将来的な機能追加やアルゴリズムの更新に対応できるよう、拡張メカニズムを維持しています。これにより、新しい鍵共有グループ、認証メカニズム、プロトコル機能などを、プロトコル全体を改訂することなく導入できます。

セキュリティ考慮

TLS 1.3は、セキュリティを最優先に設計されており、多くの攻撃リスクに対して強固な対策を講じています。

  • リプレイ攻撃 (0-RTT):

    • 0-RTTデータは、ネットワーク上の攻撃者によってキャプチャされ、サーバーに再送される「リプレイ攻撃」の対象となる可能性があります。RFC 8446では、0-RTTデータは冪等であるべき(複数回実行されても副作用がない)と推奨しており、そうでない場合はサーバー側で強力なアンチリプレイメカニズム(例: NewSessionTicketメッセージで発行されるノンストップや、クライアントのIPアドレスと時刻に基づくチェック)を実装する必要があります [1, Sec 8.4]。
  • ダウングレード攻撃への対策:

    • 前述の通り、ClientHelloメッセージ内の特別なシグナルにより、中間者によるプロトコルバージョンのダウングレード(TLS 1.3対応クライアントとサーバー間の通信をTLS 1.2以下に強制する試み)を検出します [1, Sec 4.1.2]。
  • 鍵更新 (Post-Handshake Key Update):

    • 長期にわたるTLSセッションでは、同一のトラフィック鍵を使い続けることはセキュリティリスクを増大させます。TLS 1.3では、ハンドシェイク完了後にKeyUpdateメッセージを交換することで、新しいトラフィック鍵セットを確立できます [1, Sec 4.6.3]。これにより、前方秘匿性をさらに強化し、キー漏洩時の影響範囲を限定します。
  • 前方秘匿性 (Perfect Forward Secrecy; PFS) の保証:

    • TLS 1.3では、すべての鍵交換でPFSを提供するECDHE/DHEが必須となりました [1, Sec 1]。これにより、たとえサーバーの長期的な秘密鍵が将来漏洩しても、過去のセッション鍵が再計算されることはなく、過去の通信が解読される心配はありません。
  • 弱アルゴリズムの廃止:

    • MD5、SHA-1、RC4、3DES、AES-CBCモードといった既知の脆弱性を持つ暗号アルゴリズムは、TLS 1.3から完全に削除されました [1, Appx B]。これにより、攻撃者がこれらの脆弱なアルゴリズムを悪用して通信を破る経路がなくなりました。
  • ハンドシェイクの暗号化範囲拡大:

    • TLS 1.2では平文で送信されていた多くのハンドシェイク情報(EncryptedExtensionsCertificateCertificateVerifyなど)がTLS 1.3では暗号化されます [1, Sec 1]。これにより、ネットワーク傍受者からクライアントとサーバーが利用している拡張情報やサーバー証明書などのメタデータが隠され、プライバシーが向上します。

実装メモ

TLS 1.3の実装と運用においては、パフォーマンスと信頼性を最大限に引き出すためにいくつかの点に注意が必要です。

  • MTU/Path MTUとTLSレコードサイズ:

    • TLSレコードサイズは、ネットワークの最大転送単位 (MTU) やパスMTUに配慮して決定されるべきです。特にTLSレコードを大きくしすぎると、IPフラグメンテーションが発生し、性能低下やパケットロス時の効率悪化を招く可能性があります。理想的には、TLSレコードはMTUサイズに収まるように調整し、TCPのMSS (Maximum Segment Size) と協調して動作することが望ましいです。
  • HOL blocking回避:

    • TLS 1.3自体は、TCPにおけるヘッドオブラインブロッキング (HOL blocking) 問題を直接解決するものではありませんが、その高速なハンドシェイクと0-RTT機能は、アプリケーションの初期応答時間を短縮し、HOL blockingによる体感的な遅延を軽減します。QUIC/HTTP/3のような多重化プロトコルの下で使用されることで、HOL blockingの問題は下位レイヤーでより効果的に対処されます。
  • キュー制御、優先度:

    • 0-RTTデータは、通常のアプリケーションデータよりも前に送信される可能性がありますが、リプレイ攻撃のリスクがあるため、サーバー側でその処理には注意が必要です。例えば、0-RTTデータを含むClientHelloを受け取った際、それがリプレイであると判断された場合、サーバーは早期に接続を終了するか、0-RTTデータを破棄すべきです。また、ネットワークインフラストラクチャにおいて、TLSハンドシェイクパケットや初期のアプリケーションデータに適切な優先度を割り当てることで、サービス品質 (QoS) を向上させることができます。

まとめ

TLS 1.3 (RFC 8446) は、インターネット通信のセキュリティ、パフォーマンス、プライバシーを劇的に向上させるための重要な進化です。2018年8月に公開されたこのプロトコルは、古い脆弱な暗号スイートの廃止、前方秘匿性 (PFS) の強制、ハンドシェイクの簡素化(1-RTT)、そして画期的な0-RTTハンドシェイクの導入によって、ウェブ通信の安全と高速化に貢献しています。

特に、鍵交換メカニズムはDHE/ECDHEとHKDFの利用により洗練され、堅牢なセキュリティ基盤を提供します。また、0-RTTの導入はパフォーマンスを向上させる一方で、リプレイ攻撃に対するサーバー側の厳格な対策が必須となります。ダウングレード攻撃保護や鍵更新機能により、現代の脅威に対応できる設計が施されています。

ネットワークエンジニアとして、TLS 1.3のこれらの特性を理解し、適切に実装・運用することは、ユーザーに安全で高速なオンライン体験を提供する上で不可欠です。


参照: [1] IETF. “The Transport Layer Security (TLS) Protocol Version 1.3.” RFC 8446. August 2018. https://datatracker.ietf.org/doc/html/rfc8446 (参照日: 2024年7月30日)

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

コメント

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