TLS ハンドシェイクの流れ

入門 | 10分 で読める | 2026.05.02

公式ドキュメント

この記事の要点

TLS ハンドシェイクは、暗号化通信を始める前に鍵交換と認証を行うプロセス
• TLS 1.2 は 2-RTT(往復 2 回)、TLS 1.3 は 1-RTT(往復 1 回)で高速化
ECDHE 鍵交換 + 証明書検証 + 共通鍵生成の 3 ステップで安全な通信を確立

TLS ハンドシェイクとは

TLS ハンドシェイクは、クライアントとサーバーが暗号化通信を開始する前に、使用する暗号方式の合意鍵の交換サーバーの認証を行うプロセスです。

HTTPS との関係: HTTPS は「HTTP over TLS」です。HTTP 通信の前に、まず TLS ハンドシェイクで暗号化チャネルを確立します。

TLS ハンドシェイクの目的

目的内容
暗号方式の合意クライアントとサーバーが対応している暗号スイートの中から使用するものを選択
鍵の交換公開鍵暗号を使って、安全に共通鍵(セッション鍵)を生成・共有
サーバー認証サーバーが本物であることを証明書で検証
(オプション)クライアント認証クライアント証明書による相互認証

ポイント: TLS ハンドシェイクは暗号化される前の平文通信です。ただし、鍵交換には公開鍵暗号を使うため、第三者が盗聴しても共通鍵を知ることはできません。

TLS 1.2 ハンドシェイクの流れ(2-RTT)

TLS 1.2 では、ハンドシェイクに往復 2 回(2-RTT) かかります。

クライアント                                サーバー
    |                                           |
    |-- 1. ClientHello ------------------------>|
    |                                           |
    |<- 2. ServerHello + Certificate + Done ----|
    |                                           |
    |-- 3. ClientKeyExchange + Finished ------->|
    |                                           |
    |<- 4. Finished -----------------------------|
    |                                           |
    |== 5. 暗号化通信開始 ========================|

ステップ 1: ClientHello

クライアントがサポートする暗号スイートとパラメータをサーバーに送信します。

ClientHello:
- TLS Version: 1.2
- Random: (32 バイトの乱数)
- Cipher Suites:
  - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  - ...
- Extensions:
  - server_name: example.com (SNI)
  - supported_groups: x25519, secp256r1
  - ec_point_formats: uncompressed
フィールド内容
TLS Versionサポートする TLS バージョン(1.2, 1.3 など)
Random後で共通鍵を生成する際に使う乱数
Cipher Suites暗号化・鍵交換・MAC のセット
SNI(Server Name Indication)複数ドメイン対応のため、どのホスト名にアクセスしているかを通知

実践メモ: SNI は平文で送られるため、暗号化前に第三者に見られます。これを隠すための ECH(Encrypted Client Hello)という新技術が開発中です。

ステップ 2: ServerHello + Certificate + ServerKeyExchange + ServerHelloDone

サーバーが暗号スイートを選択し、証明書と鍵交換パラメータを返します。

ServerHello:
- TLS Version: 1.2
- Random: (32 バイトの乱数)
- Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256

Certificate:
- Server Certificate Chain(サーバー証明書と中間証明書)

ServerKeyExchange:
- ECDHE Public Key(サーバーの ECDHE 公開鍵)

ServerHelloDone:
- (メッセージの終了を示す)
メッセージ内容
ServerHello使用する暗号スイート・TLS バージョンを確定
Certificateサーバーの SSL/TLS 証明書(公開鍵を含む)
ServerKeyExchangeECDHE など鍵交換のパラメータ
ServerHelloDoneサーバー側のメッセージ送信完了

ステップ 3: ClientKeyExchange + ChangeCipherSpec + Finished

クライアントが鍵交換パラメータを送り、共通鍵を生成して暗号化を開始します。

ClientKeyExchange:
- ECDHE Public Key(クライアントの ECDHE 公開鍵)

ChangeCipherSpec:
- (以降のメッセージを暗号化することを通知)

Finished:
- (ハンドシェイクメッセージの MAC、暗号化されている)

この時点で、クライアントとサーバーは同じ共通鍵(セッション鍵) を持ちます。

ステップ 4: ChangeCipherSpec + Finished(サーバー)

サーバーも暗号化を開始し、ハンドシェイクが完了します。

ChangeCipherSpec:
- (以降のメッセージを暗号化することを通知)

Finished:
- (ハンドシェイクメッセージの MAC、暗号化されている)

ステップ 5: 暗号化通信開始

以降、HTTP リクエスト/レスポンスは共通鍵で暗号化されます。

[クライアント] --暗号化された HTTP リクエスト--> [サーバー]
[クライアント] <--暗号化された HTTP レスポンス-- [サーバー]

ポイント: TLS 1.2 では、ClientHello → ServerHello で 1 往復、ClientKeyExchange → Finished で 1 往復の計 2-RTTかかります。これが TLS 1.3 で 1-RTT に短縮されました。

TLS 1.3 ハンドシェイクの流れ(1-RTT)

TLS 1.3 では、ハンドシェイクが往復 1 回(1-RTT) に短縮されました。

クライアント                                サーバー
    |                                           |
    |-- 1. ClientHello + KeyShare ------------->|
    |                                           |
    |<- 2. ServerHello + KeyShare + Finished ---|
    |                                           |
    |-- 3. Finished ---------------------------->|
    |                                           |
    |== 4. 暗号化通信開始 ========================|

主な改善点

項目TLS 1.2TLS 1.3改善内容
ハンドシェイク往復回数2-RTT1-RTT接続が 1 往復分高速化
鍵交換方式RSA, DHE, ECDHEECDHE のみ前方秘匿性(Forward Secrecy)が必須
暗号化開始タイミングFinished 後ServerHello 直後Certificate など一部が暗号化される
古い暗号の削除-RSA 鍵交換、RC4、3DES、MD5 など削除セキュリティ強化

ステップ 1: ClientHello + KeyShare

TLS 1.3 では、ClientHello に鍵交換パラメータ(KeyShare)を同時に送信します。

ClientHello:
- TLS Version: 1.3
- Random: (32 バイトの乱数)
- Cipher Suites:
  - TLS_AES_128_GCM_SHA256
  - TLS_AES_256_GCM_SHA384
- Extensions:
  - server_name: example.com (SNI)
  - key_share: (ECDHE 公開鍵を含む)
  - supported_groups: x25519, secp256r1

ポイント: TLS 1.2 では ClientHello → ServerHello の後に鍵交換していましたが、TLS 1.3 では最初から鍵交換パラメータを送ることで 1 往復削減しています。

ステップ 2: ServerHello + KeyShare + Certificate + Finished

サーバーが鍵交換パラメータと証明書を返し、この時点で暗号化を開始します。

ServerHello:
- TLS Version: 1.3
- Random: (32 バイトの乱数)
- Cipher Suite: TLS_AES_128_GCM_SHA256
- key_share: (ECDHE 公開鍵)

EncryptedExtensions:(ここから暗号化)
- Extensions...

Certificate:
- Server Certificate Chain(暗号化されている)

CertificateVerify:
- 証明書の署名検証(暗号化されている)

Finished:
- ハンドシェイクメッセージの MAC(暗号化されている)

ステップ 3: Finished(クライアント)

クライアントが証明書を検証し、ハンドシェイク完了を通知します。

Finished:
- ハンドシェイクメッセージの MAC(暗号化されている)

ステップ 4: 暗号化通信開始

以降、HTTP リクエスト/レスポンスを交換します。

ポイント: TLS 1.3 ではCertificate が暗号化されて送信されるため、盗聴者にサーバー証明書の内容(ドメイン名など)が見えません。プライバシーが向上しています。

TLS 1.2 vs TLS 1.3 比較表

項目TLS 1.2TLS 1.3
ハンドシェイク RTT2-RTT1-RTT
鍵交換RSA, DHE, ECDHEECDHE のみ(前方秘匿性必須)
暗号スイート数37 種類5 種類(安全なもののみ)
Certificate の暗号化✕(平文)◎(暗号化)
0-RTT(再接続)◎(オプション、リプレイ攻撃注意)
削除された暗号-RSA 鍵交換、RC4, 3DES, MD5, SHA-1
セッション再開Session ID / Session TicketPSK (Pre-Shared Key)

注意: TLS 1.3 の 0-RTT(再接続時にハンドシェイクをスキップ)は高速ですが、リプレイ攻撃のリスクがあります。冪等でない操作(POST リクエストなど)では使用を避けてください。

ECDHE 鍵交換の仕組み

ECDHE(Elliptic Curve Diffie-Hellman Ephemeral)は、TLS 1.3 で必須となった鍵交換方式です。

ECDHE の流れ

1. クライアントが秘密鍵 a を生成し、公開鍵 A を計算
   A = a × G(G は楕円曲線の基準点)

2. サーバーが秘密鍵 b を生成し、公開鍵 B を計算
   B = b × G

3. お互いの公開鍵を交換
   クライアント → サーバー: A
   サーバー → クライアント: B

4. 共通鍵を計算
   クライアント: S = a × B
   サーバー: S = b × A
   → どちらも S = a × b × G になり、同じ値になる
特徴内容
前方秘匿性(Forward Secrecy)セッションごとに鍵を生成。過去の通信は秘密鍵が漏れても解読されない
Ephemeral(一時的)ハンドシェイクごとに新しい鍵ペアを生成
盗聴耐性公開鍵 A, B を盗聴しても、秘密鍵 a, b がないと共通鍵 S を計算できない

ポイント: RSA 鍵交換では、サーバーの秘密鍵が漏れると過去の通信も全て解読されます。ECDHE ではセッションごとに鍵が変わるため、過去の通信は安全です。

証明書検証の流れ

TLS ハンドシェイク中に、クライアントはサーバー証明書を検証します。

検証項目

検証項目内容
証明書チェーンサーバー証明書 → 中間証明書 → ルート CA の信頼の連鎖を確認
有効期限現在日時が証明書の有効期間内か
ドメイン名証明書の CN(Common Name)または SAN(Subject Alternative Name)が接続先ドメインと一致するか
失効確認CRL(Certificate Revocation List)または OCSP(Online Certificate Status Protocol)で失効していないか
署名検証上位 CA の公開鍵で証明書の署名を検証

証明書チェーンの例

[ルート CA](ブラウザに内蔵)
    ↓ 署名
[中間 CA]
    ↓ 署名
[サーバー証明書]
サーバー証明書:
- Subject: CN=example.com
- Issuer: CN=Let's Encrypt Authority X3
- Public Key: (RSA 2048 bit)
- Signature: (中間 CA の秘密鍵で署名)

中間証明書:
- Subject: CN=Let's Encrypt Authority X3
- Issuer: CN=DST Root CA X3
- Signature: (ルート CA の秘密鍵で署名)

クライアントは、ルート CA の公開鍵(ブラウザに内蔵)で中間証明書を検証し、中間証明書の公開鍵でサーバー証明書を検証します。

実践メモ: Chrome DevTools の Security タブで、接続先サイトの証明書チェーンを確認できます。Let's Encrypt などの証明書がどのように検証されているか見てみましょう。

SNI(Server Name Indication)

1 つの IP アドレスで複数のドメインを運用する場合、SNI で接続先のホスト名を通知します。

ClientHello:
- Extensions:
  - server_name: blog.example.com

サーバーは SNI を見て、対応する証明書を返します。

SNI なしSNI あり
1 つの IP = 1 つの証明書1 つの IP = 複数の証明書(ドメインごと)
古い TLS 実装(TLS 1.0 以前)TLS 1.1 以降、現代の標準

注意: SNI は平文で送信されるため、盗聴者に接続先ドメインがわかります。これを防ぐ ECH(Encrypted Client Hello)が TLS 1.3 の拡張として標準化中です。

ALPN(Application-Layer Protocol Negotiation)

TLS ハンドシェイク中に、どのアプリケーション層プロトコルを使うかを決めます。

ClientHello:
- Extensions:
  - alpn: h2, http/1.1
ServerHello:
- Extensions:
  - alpn: h2

これにより、HTTP/2(h2)と HTTP/1.1 のどちらを使うかをハンドシェイク時に決定できます。

用途ALPN の値
HTTP/2h2
HTTP/1.1http/1.1
HTTP/3(QUIC)h3

ポイント: ALPN がなかった時代は、TLS ハンドシェイク後に NPN(Next Protocol Negotiation)を使っていましたが、ALPN に置き換えられました。

まとめ

TLS ハンドシェイクは、暗号化通信を開始する前の鍵交換・認証・暗号方式の合意を行うプロセスです。

TLS バージョンハンドシェイク RTT鍵交換セキュリティ
TLS 1.22-RTTRSA / ECDHE古い暗号も残る
TLS 1.31-RTTECDHE のみ安全な暗号のみ、Certificate 暗号化

TLS 1.3 では、1-RTT ハンドシェイク前方秘匿性必須により、速度とセキュリティの両方が向上しています。現代の Web インフラでは TLS 1.3 の導入が推奨されます。

参考リソース

この技術を体系的に学びたいですか?

未来学では東証プライム上場企業のITエンジニアが24時間サポート。月額24,800円から、退会金0円のオンラインIT塾です。

メールで無料相談する
← 一覧に戻る