ウェブブラウザで URLURL [ユーアールエル]Uniform Resource Locator。Webページのアドレス の先頭が https:// で始まるサイトにアクセスすると、通信内容は第三者から盗聴・改ざんされないよう暗号化されます。この安全な通信を実現しているプロトコルが TLSTLS [ティーエルエス]Transport Layer Security。SSLの後継となる安全性の高い暗号化通信プロトコル(Transport Layer Security) です。
ブラウザとウェブサーバーが暗号化通信を始める前には、お互いに挨拶を交わし、どの暗号化方式を使うかを合意し、暗号化用の「共通鍵」を安全に取り決める準備工程が存在します。この準備工程を TLSハンドシェイク と呼びます。
この記事では、TLSハンドシェイクの役割や仕組み、ハイブリッド暗号方式の考え方、そして現在広く利用されている TLS 1.2 と現在の TLS の最新バージョンである TLS 1.3 のシーケンスの違いを実機ログを交えて分かりやすく解説します。
TLSハンドシェイクとは?3つの重要な役割
TLSハンドシェイクは、通信相手との安全な通信を確立するために実行されます。HTTPHTTP [エイチティーティーピー]HyperText Transfer Protocol。Webでのデータ転送プロトコル/1.1 や HTTP/2 など、TCPTCP [ティーシーピー]Transmission Control Protocol。信頼性の高い通信プロトコル 上で TLS を利用する場合は、TCPの3ウェイハンドシェイク によってコネクションが確立された後に実行されます。一方、HTTP/3 では QUIC を利用するため、TCP の 3 ウェイハンドシェイクは行われず、QUIC の接続確立と TLS 1.3 のハンドシェイクが連携して実行されます。主な目的は以下の 3点 です。
- 暗号スイート(Cipher Suite)の合意: 通信双方がサポートしている暗号アルゴリズムをすり合わせ、使用する組み合わせを決定します。TLS 1.2 では、鍵交換方式・署名方式・暗号化方式・ハッシュ関数などを組み合わせた暗号スイートを選択します。一方、TLS 1.3 では暗号スイートが暗号化方式とハッシュ関数の組み合わせを定義し、鍵交換方式や署名方式は別途ネゴシエーションされます。
- サーバーの身元証明(認証): サーバーから送られてくる デジタル証明書 と電子署名をクライアントが検証し、接続先が本物のサーバーであることを確認します(なりすましの防止。TLS ではクライアント認証も可能ですが、一般的な Web 通信ではサーバー認証が中心です)。
- セッション鍵(共通鍵)の共有: 実際のデータ通信を暗号化するために使う セッション鍵 を、通信経路上の盗聴者に知られることなく安全に生成・共有します。
なぜハイブリッド暗号方式を採用するのか
暗号化には大きく分けて 共通鍵暗号方式 と 公開鍵暗号技術 の2つがあります(詳しくは RSAとAESの違い や 暗号化方式の種類と特徴 をご覧ください)。
- 共通鍵暗号方式(AESやChaCha20など): 暗号化と復号に同じ鍵を使う。処理速度が非常に高速だが、鍵を相手に安全に届ける方法(鍵配送問題)が必要。
- 公開鍵暗号技術(RSA、ECDSA、ECDHなど): 公開鍵と秘密鍵のペアを利用する暗号技術です。RSA は公開鍵暗号や電子署名に利用され、ECDSA は電子署名、ECDH は鍵共有に利用されます。これらの技術は共通鍵暗号とは異なる役割を持ち、TLS では鍵共有やサーバー認証などに利用されます。
TLSでは、両者の長所を組み合わせた ハイブリッド暗号方式 を採用しています。
ハンドシェイクの段階では公開鍵暗号や鍵交換アルゴリズム(Diffie-Hellman鍵共有)を利用して、安全に セッション鍵(共通鍵) を取り決めます。そしてハンドシェイク完了後の実際のWebページ送受信(HTTPリクエスト/レスポンス)では、処理が高速な 共通鍵暗号 を用いてデータを暗号化します。
TLS 1.2のハンドシェイク手順(従来の2-RTT)
TLS 1.2 は 2008 年に策定された仕様(RFC 5246)で、長年にわたりインターネットを支えてきました。TLS 1.2 の新規フルハンドシェイクでは、暗号化通信を開始するまでに基本的に 2往復(2-RTT: Round Trip Time) のやり取りが必要です。ただし、過去に確立したセッション情報を再利用するセッション再開では、短縮ハンドシェイクによって 1往復(1-RTT)で完了する場合もあります。
なお、以下のシーケンス図は ECDHE を利用した TLS 1.2 のフルハンドシェイクを例にしています。実際のメッセージ構成は鍵交換方式によって異なり、RSA 鍵交換方式などでは Server Key Exchange が送信されない場合もあります。
各ステップの具体的な動作は次のとおりです。
1. Client Hello
クライアントがサーバーに対して通信開始をリクエストします。送信内容には以下が含まれます。
- クライアントがサポートする TLS バージョン
- 暗号スイートの候補一覧
- クライアント乱数(Client Random: 後で鍵を生成するためのランダムな値)
- 接続先ホスト名(SNI: Server Name Indication)
2. Server Hello 〜 Server Hello Done
サーバーはクライアントの提案を受けて以下を返します。
- Server Hello: 提示された候補の中からサーバーが選択した TLS バージョンと暗号スイート、サーバー乱数(Server Random)
- Certificate: サーバーの公開鍵が含まれたデジタル証明書
- Server Key Exchange: ECDHE(楕円曲線ディフィー・ヘルマン)等の鍵共有に必要な公開パラメータと、サーバー秘密鍵によるデジタル署名
- Server Hello Done: 挨拶情報の送信完了通知
3. Client Key Exchange 〜 Finished
クライアントは受信したサーバー証明書について、信頼できる認証局(CA)まで証明書チェーンをたどれるか、署名が正しいか、有効期限内であるか、接続先のホスト名と証明書の SAN(Subject Alternative Name)が一致するかなどを検証します。これにより、接続先サーバーの正当性を確認したうえで鍵交換パラメータを送信します。
- Client Key Exchange: 自身の鍵交換パラメータを送信
- クライアントとサーバーは、鍵交換方式に応じて プリマスターシークレット(Pre-Master Secret) を共有・生成します。その後、プリマスターシークレットとクライアント乱数、サーバー乱数を使用して マスターシークレット を導出し、さらにマスターシークレットなどから実際の通信に使用する暗号化鍵やMAC鍵(AEAD暗号を使用する場合はAEAD用の鍵とIVなど)を生成します。
- Change Cipher Spec: 「ここからの通信は決定した暗号化方式と鍵で送信する」という合図
- Finished: ここまでのハンドシェイク内容が改ざんされていないかを検証するための暗号化メッセージ
4. サーバーの Finished
サーバー側も同様に Change Cipher Spec と Finished を返し、双方が正しく復号できることを確認したらハンドシェイクは完了です。
TLS 1.2の実機通信ログ
LinuxLinux [リナックス / ライナックス]オープンソースのOSカーネル 環境で curl コマンドを使用して TLS 1.2 を明示的に指定した場合のハンドシェイクログの例を確認してみます(※表示される IPIP [アイピー]Internet Protocol。インターネット通信の基本プロトコル アドレスや暗号スイート、ログの表記形式は接続時期や環境によって異なります)。
curl -v --tlsv1.2 --tls-max 1.2 https://example.com 2>&1 | grep -E '(\* TLS|\* SSL|\* Connected)'* Connected to example.com (104.20.23.154) port 443 (#0)* TLSv1.2 (OUT), TLS handshake, Client hello (1):* TLSv1.2 (IN), TLS handshake, Server hello (2):* TLSv1.2 (IN), TLS handshake, Certificate (11):* TLSv1.2 (IN), TLS handshake, Server key exchange (12):* TLSv1.2 (IN), TLS handshake, Server hello done (14):* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):* TLSv1.2 (OUT), TLS handshake, Finished (20):* TLSv1.2 (IN), TLS handshake, Finished (20):* SSL connection using TLSv1.2 / ECDHE-ECDSA-CHACHA20-POLY1305ログを見ると、Client hello、Server hello、Certificate、Server key exchange、Server hello done、Client key exchange、Finished という段階を経て接続が確立されていることが確認できます(※使用する TLS ライブラリの種類やバージョンによっては、受信側の Change cipher spec など一部のメッセージ表示が省略される場合があります)。
TLS 1.3のハンドシェイク手順(最新の1-RTT)
TLS 1.3 は 2018 年に RFC 8446 として標準化された仕様です。速度向上とセキュリティ強化を両立するため、ハンドシェイクの構造が大幅に見直されました。
最大の特徴は、通常の新規フルハンドシェイクに必要な往復回数が従来の 2-RTT から 1-RTT に半減 したことです(なお、Client Hello に含めた Key Share がサーバーの対応する鍵交換グループと一致しない場合は HelloRetryRequest が送信され、追加の往復が発生します)。
なお、以下のシーケンス図は TCP 上で TLS 1.3 を利用する場合の例です。HTTP/3 の場合は QUIC の接続確立と TLS 1.3 のハンドシェイクが連携するため、別のシーケンスになります。
なぜ1-RTTで完了できるのか?(Key Share拡張)
TLS 1.2 では、サーバーが選んだ鍵交換方式を確認してからクライアントが鍵パラメータ(Client Key Exchange)を送っていました。
一方 TLS 1.3 では、クライアントが最初の Client Hello の時点で、対応可能な鍵交換グループ(X25519など)と、鍵共有パラメータ(Key Share拡張)をあらかじめ送信します。これにより、サーバーは Client Hello を受け取った後、自身の鍵共有パラメータを生成して共通の秘密情報を計算できるため、追加の往復を待たずに鍵交換を進められます。なお、サーバーはクライアントが提示した Key Share に対応できない場合、HelloRetryRequest を送信します。
サーバーは Client Hello を受け取った時点で暗号化用の鍵(ハンドシェイク用の鍵)を生成できるため、Server Hello と同時に自身の Key Share を返し、 その直後の証明書や Finished メッセージをすでに暗号化した状態で送信 できます。なお、TLS 1.3 では Certificate Verify によって、サーバーが証明書に対応する秘密鍵を保持していることも確認します。
これにより、わずか 1往復(1-RTT) で安全なデータ通信を開始できます。
TLS 1.3の実機通信ログ
curl コマンドで TLS 1.3 を明示的に指定して接続を行った際のログの例を確認してみます(※表示される IP アドレスや暗号スイート、ログの表記形式は接続時期や環境によって異なります)。
curl -v --tlsv1.3 https://example.com 2>&1 | grep -E '(\* TLS|\* SSL|\* Connected)'* Connected to example.com (172.66.147.243) port 443 (#0)* TLSv1.3 (OUT), TLS handshake, Client hello (1):* TLSv1.3 (IN), TLS handshake, Server hello (2):* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):* TLSv1.3 (IN), TLS handshake, Certificate (11):* TLSv1.3 (IN), TLS handshake, CERT verify (15):* TLSv1.3 (IN), TLS handshake, Finished (20):* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):* TLSv1.3 (OUT), TLS handshake, Finished (20):* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384TLS 1.3 では、Server hello に続いて Encrypted Extensions や暗号化された Certificate が届き、往復ステップが大幅に短縮されていることが分かります。
なお、ログに Change cipher spec が出力されていますが、TLS 1.3 では従来のように暗号化開始を通知する目的では使用されません。これは、TLS 1.3 に対応していない中間装置(Middlebox)との互換性を高めるためのダミーメッセージ(Compatibility Mode)であり、受信側では無視されます。TLS 1.3 では、Server Hello の後に鍵導出が行われ、以降のハンドシェイクメッセージはハンドシェイク用の鍵で暗号化されます。
0-RTT(Early Data)による高速再開
TLS 1.3 では PSK(Pre-Shared Key)を利用したセッション再開が可能で、通常は 1-RTT で再開できます。さらにオプションとして、過去に接続した実績のあるサーバーに対して、最初の通信フライトで Client Hello とともに、暗号化した HTTP リクエストデータ(Early Data)を送信できる 0-RTT(Zero Round Trip Time)モード も用意されています。
RTT なしで即座にデータ通信が開始できる強力な仕組みですが、パケットを傍受した第三者が同じリクエストを再送信できてしまう リプレイ攻撃(Replay Attack) のリスクがあります。なお、0-RTT で送信されるデータは通常の 1-RTT 通信と異なり前方秘匿性が保証されず、リプレイ攻撃への対策も必要です。そのため、サーバー側ではリプレイされても問題が生じない処理に限定するなど、アプリケーションレベルでの対策が重要になります(HTTP メソッド名だけで安全性を判断せず、副作用がない処理かどうかの見極めが必要です)。
TLS 1.2 と TLS 1.3 の主要な違い
TLS 1.3 は単に接続が速くなっただけでなく、設計思想そのものが大きく刷新されています。主な違いを比較表でまとめました。
| 比較項目 | TLS 1.2 | TLS 1.3 |
|---|---|---|
| 新規接続時の往復回数 | 2-RTT | 1-RTT |
| セッション再開時の往復 | 1-RTT | 1-RTT(通常)/ 0-RTT(Early Data利用時) |
| 鍵交換方式 | 静的RSA、DHE、ECDHE、PSKなど | (EC)DHE、PSK、PSK + (EC)DHE |
| 静的RSA暗号の扱い | サポート(前方秘匿性なし) | 完全廃止 |
| 暗号スイート | 鍵交換方式や認証方式なども組み合わせて定義 | AEAD暗号とハッシュ関数の組み合わせを定義 |
| 証明書等の暗号化 | 平文で送出(盗聴可能) | Server Helloの直後のメッセージから暗号化 |
| 脆弱な暗号(CBC, RC4等) | 一部残存 | 暗号スイートから排除(AEAD暗号のみ) |
Forward Secrecy(前方秘匿性)の強化
従来の TLS 1.2 で広く使われていた「静的 RSA 鍵交換」では、サーバーの秘密鍵が将来漏洩した場合、過去に盗聴・記録されていた暗号化通信がすべて解読されてしまうという致命的な弱点(前方秘匿性がない状態)がありました。
TLS 1.3 では静的 RSA 鍵交換が廃止され、新規フルハンドシェイクでは一時的な Diffie-Hellman(ECDHE / DHE)鍵交換 が使用されます。これにより、仮に将来サーバーの秘密鍵が漏洩しても過去の通信は復号できません。また、セッション再開では PSK を利用できますが、PSK 単独の方式(psk_ke)では前方秘匿性が提供されません。PSK と ECDHE / DHE を組み合わせる方式(psk_dhe_ke)では、前方秘匿性を確保できます。
脆弱なアルゴリズムの排除とAEAD暗号への統一
TLS 1.3 の RFC 8446 で定義された標準の暗号スイートでは、使用するハッシュ関数が SHA-256 または SHA-384 に限定されており、SHA-1 を利用する従来の暗号スイートは採用されていません。また、過去に POODLE や BEAST などの脆弱性の原因となった CBC(Cipher Block Chaining)モードや RC4 などのレガシーな暗号方式も TLS 1.3 の暗号スイートから排除されています。
採用される暗号化方式は、データの暗号化と改ざん検知を同時に行える AEAD(Authenticated Encryptionencryption [エンクリプション]データを暗号化する処理 with Associated Data) のみ(AES-GCM や ChaCha20-Poly1305 等)に限定されています。
なお、RFC 8446 では TLS 1.3 の暗号スイートが 5 種類定義されています。TLS 1.2 以前とは異なり、TLS 1.3 の暗号スイートはデータ暗号化方式とハッシュ関数の組み合わせを定義しており、鍵交換方式や署名方式は別の拡張情報によってネゴシエーションされるため、暗号スイートの設計自体もシンプルになっています。
OpenSSLコマンドでハンドシェイク情報を確認する方法
自身のサーバーや検証環境で TLS の接続状態を調査したい場合、Linux に標準搭載されている openssl s_client コマンドが役立ちます。
サーバーの証明書チェーンとプロトコルを確認する
openssl s_client は診断用ツールであり、デフォルトでは証明書の検証エラーが発生しても接続を継続し、ホスト名(SAN)の一致検証も行われません。厳密に検証する場合は、次のようにオプションを指定して実行します。
openssl s_client \ -connect example.com:443 \ -servername example.com \ -tls1_3 \ -verify_return_error \ -verify_hostname example.com \ < /dev/null各オプションの意味は次のとおりです。
-connect: 接続先ホストとポートを指定-servername: SNI で送信するホスト名を指定-tls1_3: TLS 1.3 を使用-verify_return_error: 証明書の検証エラーが発生した場合に接続を失敗させる-verify_hostname: 証明書のホスト名が接続先と一致するかを検証
実行結果の一部(抜粋):
CONNECTED(00000005)Certificate chain 0 s:CN = example.com i:C = US, O = SSL Corporation, CN = Cloudflare TLS Issuing ECC CA 3 1 s:C = US, O = SSL Corporation, CN = Cloudflare TLS Issuing ECC CA 3 i:C = US, O = SSL Corporation, CN = SSL.com TLS Transit ECC CA R2New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384Server public key is 256 bitSecure Renegotiation IS NOT supportedCompression: NONEExpansion: NONENo ALPN negotiatedEarly data was not sentVerify return code: 0 (ok)この結果から、以下の重要な項目が確認できます。
- 使用プロトコル:
TLSv1.3 - 選択された暗号スイート:
TLS_AES_256_GCM_SHA384 - サーバー証明書の検証結果:
Verify return code: 0 (ok)(証明書チェーンの検証に成功し、指定したホスト名との一致も確認できた状態)
接続エラーや証明書期限切れのトラブルシューティングを行う際は、まず openssl s_client を実行してどの段階でハンドシェイクが失敗しているかを確認するのが定石です。
まとめ
TLSハンドシェイクのポイントをまとめます。
- TLSハンドシェイクの目的: 暗号スイートの合意、サーバーの身元認証、共通鍵(セッション鍵)の安全な共有の3つ。
- ハイブリッド暗号方式: 鍵の安全な受け渡しに公開鍵暗号・鍵交換を用い、実データの送受信には高速な共通鍵暗号を用いる。
- TLS 1.2 と 1.3 の最大の違い: TLS 1.2 の新規フルハンドシェイクでは 2-RTT かかっていた処理が、TLS 1.3 では Client Hello で Key Share をあらかじめ送信することにより 1-RTT(セッション再開時は通常 1-RTT、Early Data 利用時は 0-RTT)へ短縮。
- セキュリティの強化: TLS 1.3 では静的 RSA 鍵交換が廃止されて新規フルハンドシェイクでの前方秘匿性(PFS)が確保され、CBC モードや RC4 などのレガシーな暗号方式も暗号スイートから排除された。
現在の Web サイトでは TLS 1.2 と TLS 1.3 が広く利用されています。TLS 1.3 はセキュリティと通信性能の両面で改善されており、新しい環境では TLS 1.3 の利用が推奨されます。ネットワークやセキュリティの基礎知識として、ハンドシェイクの流れを押さえておきましょう。
以上で本記事の解説を終わります。
よいITライフを!
人気記事
- 1
- 2
- 3
- 4
- 5
思考の整理というテーマを、実務ですぐに使える具体的な「技術」として落とし込んだ一冊です。