このページの目次

TLS 1.3 ハンドシェイク

TLS 1.3 はハンドシェイクを 1-RTT、0-RTT、さらにはゼロラウンドトリップに圧縮します。その手段は、静的 RSA の削除、前方秘匿性の強制、鍵合意を ClientHello に前倒しすることです。潔いプロトコル設計ですが、その代償として 0-RTT はリプレイ保護を失います。

概要

TLS 1.3 (RFC 8446、2018) は TLS 1.2 にとって最大のリビジョンであり、その核心となる手法は一言で表せます。⁠クライアントは「サーバーは何を使いたいか」と問いかけるのではなく、直接推測する⁠——ClientHello に ECDHE 公開鍵 (key_share) を含め、サーバーが x25519 をサポートしていることを賭けます(ほぼ必ず当たります)。これにより、TLS 1.2 で見られた「まずアルゴリズムを合意し、次に鍵を交換する」という 2 ラウンドのやり取りが 1 ラウンドに収縮し、セッションチケットがある場合はゼロラウンドトリップ (0-RTT) すら可能になります。

設計目標は以下の 4 点です。

  1. ハンドシェイクのラウンドトリップ削減⁠: 2-RTT → 1-RTT (初回)、0-RTT (再接続)
  2. 安全でないアルゴリズムの削除⁠: 静的 RSA 鍵交換、CBC、RC4、MD5/SHA-1——過去に問題を起こしたものはすべて排除
  3. より多くのハンドシェイクメッセージの暗号化⁠: ServerHello 以降はすべて暗号化され、傍受者でも証明書を見ることができません
  4. 簡素化⁠: 約 100 個あった暗号スイートを 5 個に削減

TLS 1.2 との重要な違いを以下の一覧で確認できます。

TLS 1.2TLS 1.3
初回ハンドシェイク2-RTT1-RTT
セッション再開session ID / ticket、1-RTTPSK、0-RTT
鍵交換RSA または (EC)DHE(EC)DHE のみ → 前方秘匿性の強制
ハンドシェイク暗号化全明文ServerHello 以降は全暗号化
Cipher suite~100 個、鍵交換+署名を含む5 個、AEAD + ハッシュのみを含む
鍵導出PRFHKDF

1-RTT 完全ハンドシェイクフロー

sequenceDiagram
    participant C as Client
    participant S as Server
    C->>S: ClientHello<br>key_share(x25519 公開鍵), cipher_suites,<br>supported_groups, signature_algorithms
    Note over S: 共有鍵を算出可能<br>→ 以降のメッセージはすべて暗号化
    S->>C: ServerHello (key_share)<br>🔒 EncryptedExtensions<br>🔒 Certificate + CertificateVerify<br>🔒 Finished
    Note over C: 証明書と署名を検証し、<br>同じ鍵を算出
    C->>S: 🔒 Finished + アプリケーションデータ
    Note over C,S: 最初の RTT 終了時点でデータは進行中<br>(TLS 1.2 では 2 RTT 待つ必要がある)

このフローには 3 つの設計上のポイントが隠されています。

key_share: 鍵合意の前倒し⁠。クライアントは各楕円曲線に対して ECDHE 公開鍵 (x25519 は 32 バイト、secp256r1 は 65 バイト) を付加し、サーバーは曲線を選択して自身の公開鍵を返します——これにより、双方は最初のラウンド内で Diffie-Hellman を完了します。もし外れた場合はどうなるでしょうか?サーバーは HelloRetryRequest を返し曲線を指定し、クライアントは ClientHello を再送し、2-RTT に後退します——ただし実務上、ほぼ発生しません。

認証と機密性の分離⁠。TLS 1.2 の静的 RSA では、2 つのことが結びついていました。サーバーの秘密鍵は身元証明にも、鍵の復号にも使われました——秘密鍵が漏洩すると、過去に記録されたすべてのトラフィックを再生して復号できてしまいます。TLS 1.3 では、鍵は毎回新規の ECDHE からのみ生成されます (⁠前方秘匿性⁠)。証明書秘密鍵は単一の役割、つまりハンドシェイクレコードへの署名 (CertificateVerify) を行い、「私がこのドメインの正当な所有者であること」を証明します。

Cipher suite は AEAD + ハッシュの組み合わせのみ⁠:

Suite用途
TLS_AES_128_GCM_SHA256デフォルトの主力
TLS_AES_256_GCM_SHA384より高い安全マージン
TLS_CHACHA20_POLY1305_SHA256AES ハードウェアアクセラレーションがないモバイル向け
TLS_AES_128_CCM_SHA256 / CCM_8IoT 制約付きデバイス向け

鍵導出: HKDF

TLS 1.3 では、1.2 の PRF に代わって HKDF が使用され、導出チェーンは 3 段階の「鍵の階段」となっています。

Early Secret     = HKDF-Extract(salt=0, PSK または 0)          ← 0-RTT 用鍵はこの層から生成
Handshake Secret = HKDF-Extract(Early Secret, ECDHE 共有鍵) ← ハンドシェイク暗号化用鍵
Master Secret    = HKDF-Extract(Handshake Secret, 0)        ← アプリケーションデータ用鍵

各 Expand 処理では、transcript hash(これまでに送信されたすべてのハンドシェイクメッセージのハッシュ) が混入されます。そのため、たとえ 2 回のハンドシェイクで同じ PSK を使用しても、メッセージのいずれか 1 バイトでも異なれば、導出される鍵は完全に異なります。これがハンドシェイクの改ざん防止の根幹です。メッセージのいずれかを改ざんすると、双方が計算する Finished チェックサムが一致しなくなります。

0-RTT PSK: 再接続時のゼロラウンドトリップ

初回ハンドシェイク後、サーバーはセッションチケット (本質的には PSK) を発行します。再接続時、クライアントは ClientHello に PSK 識別子と binder を付加し、⁠同じパケット内に暗号化されたアプリケーションデータ (early data) を直接付加します——サーバーは PSK を検証するとすぐに処理を開始し、1 ラウンドの待ち時間すら不要です。

その代償として安全性が低下するため、以下の 3 点を明確に理解する必要があります。

  • リプレイ攻撃⁠: 攻撃者がキャプチャした 0-RTT パケットをそのまま再送信すると、サーバーは early data を再度処理します。プロトコル層には完全な防御がないため、アプリケーション層で自己防衛する必要があります——0-RTT では冪等な操作のみを行う⁠(HTTP の GET/HEAD など) ことが推奨され、これが主要な CDN の実装方法です。
  • 前方秘匿性の欠如⁠: early data の鍵は PSK のみから導出されるため、PSK が漏洩すると過去のすべての 0-RTT データを復号可能になります (1-RTT 部分は新しい ECDHE が混入されているため影響を受けません)。
  • サーバーは max_early_data_size を使用してリスクを制限するか、early data を拒否して 1-RTT へのフォールバックを強制することができます。

Encrypted ClientHello (ECH)

TLS 1.3 に残された最後の平文部分: ClientHello 自体——其中的な SNI (ターゲットドメイン) により、中間デバイスが依然としてドメイン名に基づいて検閲やブロックを行う可能性があります。ECH (ESNI の後継、RFC ドラフト) はこの穴を埋めます。

  1. サーバーは DNS の HTTPS レコード (type 65) に ECH 公開鍵を公開します。
  2. クライアントは、実際の ClientHello (実際の SNI を含む) を内層として暗号化し、外層にはカモフラージュ用のドメイン (例: cloudflare-ech.com) を使用します。
  3. ECH 秘密鍵を持つサーバーのみが内層を解読可能であり、経路上の観察者はカモフラージュドメインのみを見ます。

DoH/DoT (DNS クエリ自体も暗号化されます。DNS プライバシー を参照) と組み合わせることで、「ユーザーがどのサイトにアクセスしたか」というメタデータが真に隠蔽されます。

関連

TLS 1.2 の完全なハンドシェイクとその歴史的負債については TLS 1.2 ハンドシェイク を参照してください。証明書チェーンの検証方法については 証明書と PKI を参照してください。QUIC は TLS 1.3 をトランスポート層に直接組み込んでおり、HTTP/3 を参照してください。

参考

  • RFC: 8446 (Appendix D に 0-RTT のセキュリティ分析あり)
  • ECH: draft-ietf-tls-esni
  • ツール⁠: openssl s_client -tls1_3 -connect host:443 · Wireshark フィルタ tls.handshake.type
  • 可視化⁠: tls13.xargs.org (TLS 1.3 ハンドシェイクをバイト単位で図解、非常に優れている)

Keywords: TLS 1.3, TLS1.3 ハンドシェイク手順, 1-RTT, key_share, ECDHE, 前方秘匿性, forward secrecy, 0-RTT, PSK, リプレイ攻撃, session ticket, HKDF, transcript hash, ECH, SNI, cipher suite, TLS1.2 違い