はじめに
Webサイトにアクセスする際、URLが「https://」で始まっていることに気づいたことはありませんか。この「s」は「Secure」を意味し、通信が暗号化されていることを示しています。
この暗号化通信を実現しているのがTLS(Transport Layer Security)というプロトコルです。TLSは、インターネット上でデータを安全にやり取りするための標準的な技術として広く使われています。
そして、TLS通信を開始する前に必ず行われるのがTLSハンドシェイクです。この記事では、TLSハンドシェイクの仕組みと流れについて解説します。
なぜTLSハンドシェイクが必要なのか
暗号化通信を行うには、クライアントとサーバーの間で事前に以下のことを決定する必要があります。
- どの暗号化方式を使うか
- 暗号化に使う鍵をどう共有するか
- 通信相手が本物かどうかをどう確認するか
TLSハンドシェイクは、これらを安全に取り決めるためのプロセスなのです。
TLSハンドシェイクの概要
TLSハンドシェイクの目的
TLSハンドシェイクでは、主に次の3つを実現します。
1. 暗号化方式の合意
クライアントとサーバーが、互いにサポートしている暗号化アルゴリズムの中から使用するものを選択します。これを暗号スイート(Cipher Suite)と呼びます。
2. 認証
サーバーが本物であることを証明するために、デジタル証明書を提示します。これにより、なりすましを防ぎます。
3. 鍵の共有
実際の通信で使う暗号化鍵を、安全な方法で共有します。この鍵を使って、以降のデータが暗号化されます。
TLSハンドシェイクの流れ(TLS 1.2の場合)
TLS 1.2のハンドシェイクは、複数のステップで構成されています。全体の流れを図で見てみましょう。
各ステップの詳細
1. Client Hello
クライアントがサーバーに対して最初に送信するメッセージです。以下の情報が含まれます。
- サポートしているTLSバージョン
- サポートしている暗号スイートのリスト
- ランダムな値(Client Random)
- セッションID(再接続の場合)
2. Server Hello
サーバーがクライアントに返すメッセージです。クライアントが提示した選択肢の中から、以下を決定します。
- 使用するTLSバージョン
- 使用する暗号スイート
- ランダムな値(Server Random)
3. Certificate(証明書の送信)
サーバーが自身のデジタル証明書をクライアントに送信します。この証明書には以下が含まれています。
- サーバーのドメイン名
- サーバーの公開鍵
- 証明書を発行した認証局(CA)の情報
- 証明書の有効期限
クライアントは、この証明書が信頼できる認証局によって発行されたものかを検証します。
4. Server Key Exchange
選択した暗号スイートによっては、鍵交換のための追加情報を送信します。例えば、DHE(Diffie-Hellman Ephemeral)方式の場合、鍵交換に必要なパラメータがここで送られます。
5. Server Hello Done
サーバー側のハンドシェイクメッセージの送信が完了したことを示します。
6. Client Key Exchange
クライアントが鍵交換に必要な情報を送信します。この情報とこれまでにやり取りしたClient Random、Server Randomから、マスターシークレットと呼ばれる共有鍵が生成されます。
この共有鍵から、実際の暗号化通信で使う鍵が導出されます。
7. Change Cipher Spec(クライアント)
クライアントが「これ以降のメッセージは暗号化します」と宣言します。
8. Finished(クライアント)
クライアントがこれまでのハンドシェイクメッセージのハッシュ値を暗号化して送信します。サーバーはこれを検証することで、ハンドシェイクが改ざんされていないことを確認します。
9. Change Cipher Spec(サーバー)
サーバーも「これ以降のメッセージは暗号化します」と宣言します。
10. Finished(サーバー)
サーバーもハンドシェイクメッセージのハッシュ値を暗号化して送信し、クライアントが検証します。
これで、TLSハンドシェイクが完了し、暗号化通信が開始されます。
TLS 1.3での変更点
TLS 1.3では、ハンドシェイクのプロセスが大幅に改善されました。
ハンドシェイクの高速化
TLS 1.2では、ハンドシェイクに2-RTT(Round-Trip Time:往復通信)が必要でしたが、TLS 1.3では1-RTTに削減されています。
主な変更点
1. 鍵共有の早期化
Client Helloの段階で鍵交換に必要な情報(Key Share)を送信するため、往復回数が削減されます。
2. 暗号スイートの簡素化
セキュリティ上問題のある古い暗号方式が削除され、安全な方式のみがサポートされています。
3. 0-RTTモード
過去に接続したことのあるサーバーに対しては、ハンドシェイクと同時にデータを送信できる0-RTTモードが利用可能です。ただし、リプレイ攻撃のリスクがあるため、使用には注意が必要です。
セキュリティ上のポイント
証明書検証の重要性
TLSハンドシェイクで最も重要なのが、サーバー証明書の検証です。証明書が以下の条件を満たしているか確認します。
- 信頼できる認証局によって発行されている
- 証明書の有効期限内である
- 証明書のドメイン名が接続先と一致している
- 証明書が失効していない
これらの検証を怠ると、中間者攻撃(Man-in-the-Middle Attack)を受けるリスクがあります。
暗号スイートの選択
暗号スイートには、鍵交換アルゴリズム、暗号化アルゴリズム、メッセージ認証コードなどが含まれています。
例:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- ECDHE:鍵交換方式(楕円曲線ディフィー・ヘルマン鍵交換)
- RSA:認証方式
- AES_128_GCM:暗号化アルゴリズム
- SHA256:ハッシュ関数
現代では、Perfect Forward Secrecy(完全前方秘匿性)をサポートするECDHEやDHEを使った暗号スイートが推奨されています。これにより、過去の通信が後から解読されるリスクを軽減できます。
まとめ
TLSハンドシェイクは、安全な暗号化通信を実現するための重要なプロセスです。この記事で解説した内容をまとめます。
- TLSハンドシェイクでは、暗号化方式の合意、認証、鍵の共有が行われる
- TLS 1.2では複数のステップを経て、2-RTTで完了する
- TLS 1.3では1-RTTに短縮され、パフォーマンスが向上している
- 証明書の検証と適切な暗号スイートの選択がセキュリティの鍵
普段何気なく使っているHTTPS通信の裏側で、このような複雑なやり取りが行われているのです。TLSハンドシェイクの仕組みを理解することで、Webアプリケーションのセキュリティやパフォーマンスについてより深く考えられるようになるでしょう。