ハンドシェイク
ハンドシェイクとは
SSL/TLS通信でサーバーを認証し、「公開鍵」と「秘密鍵」を使って「共通鍵」を共有する過程を「ハンドシェイク」と呼びます。
SSL/TLSセッションは、常に「ハンドシェイク」から始まります。
「ハンドシェイク」は、平文のメッセージ交換から始まり、https通信を確立するために欠くことのできないプロセスです。
SSLサーバ証明書を検証し、通信しているサーバーが真に意図したサーバーであるかの検証を行います。
サーバーがクライアントを認証する場合は、クライアント証明書を利用してクライアント認証が行われる場合もあります。
サーバーが認証されると、プリマスタ シークレットの交換、セッション キーの共有の手順に進みます。
このセッション キーが「共通鍵」となります。
RSAサーバ証明書のハンドシェイク
注:以下ではクライアントを認証を行わない手順について説明しています。
-
ClientHello:クライアントがサーバーに対して、サーバーとのSSL通信条件を決めるために必要な情報を送信します。
通信条件を決めるために送信する情報
- クライアントが利用可能なSSL/TLSバージョン番号のリスト
- 利用可能なCipherSuiteのリスト
- クライアント日時の4biteにランダムな284biteの数値を加えた324biteのランダム値
- セッションID など
- ServerHello:サーバーは、ClientHelloのリストから選択し利用を決定した通信条件をクライアントに送信します。
サーバーが決定した通信条件として送信する情報
- ClientHelloのリストから選択し利用を決定したSSL/TLSバージョン番号
- 決定したCipherSuite
- サーバー日時の4biteにランダムな284biteの数値を加えた324biteのランダム値
- セッションID など
-
現在安全とされているSSL/TLS バージョン番号はTLSv1.2です。
- CipherSuiteは「鍵交換アルゴリズム」「認証アルゴリズム」「ストリーム暗号」「ハッシュアルゴリズム」を定義します。
- サーバーのランダム値はクライアントのランダム値と合わせてクライアントがマスターキーを生成するために利用されます。
- セッションIDはClientHelloによって異なったタイプになります。新規接続の場合は新しいセッションIDが作成されます。
セッション再開の場合はクライアントとサーバーのセッションIDは同一になります。
サーバーがセッションの再開を認めない場合はnull セッションIDとなります。すなわちセッションIDは送られません。
SSL/TLSバージョン番号、CipherSuiteについて、詳しくは以下を参照してください。
- Certificate:サーバーは自身の証明書を送信します。
証明書には公開鍵が含まれています。中間証明書等、証明書のチェーンがある場合はそれらの証明書も送付されます。
- ServerHelloDone:サーバーはServerHelloDoneメッセージを送信し、Helloメッセージフェーズが終了したことを伝えます。
- ClientKeyExchange:クライアントはサーバーの証明書を検証し、認証を行います。
認証の詳細手順は以下を参照してください。
サーバーを認証できない
発生した問題情報とともにハンドシェイクの失敗が、ブラウザ等に表示されます。
サーバーの認証に成功した場合
-
クライアントは「プリマスタシークレット」と呼ばれるランダム値を作成し、証明書に含まれる公開鍵を使って暗号化します。
- クライアントは「プリマスタシークレット」をサーバーに送信します。この段階の通信自体はまだ暗号化されていませんが、「プリマスタシークレット」は暗号化されていますので第三者が解読することはできません。
- サーバーは自身の秘密鍵で「プリマスタシークレット」を復号化します。この時点で、サーバーとクライアントだけが「プリマスタシークレット」を共有できたことになります。
- ChangeCipherSpec:クライアントは以下を生成し、クライアントからの通信を暗号化するための方法Change Cipher Specをサーバーに通知します。ここまでの通信自体は暗号化されていませんが、以降の通信は暗号化されます。
- Client HelloとServer Helloに含まれていた324biteのランダム値と「プリマスタシークレット」を使って「マスタシークレット」を生成
- 「マスタシークレット」から「MACシークレット」と「セッション キー」を生成
- Finished:クライアントはFinishedメッセージをサーバーに送ります。
このメッセージはChangeCipherSpecで決められた方法で送られる最初の暗号化された通信です。サーバーはFinishedメッセージの内容をこれまでの手続き過程と照らし合わせ、正しいかどうか確認する必要があります。
- ChangeCipherSpec:サーバーも以下を生成し、サーバーからの通信を暗号化するための方法Change Cipher Specをサーバーに通知します。ここまでのサーバーからの通信は暗号化されていませんが、以降の通信は暗号化されます。
サーバーの生成した「マスタシークレット」、「MACシークレット」、「セッション キー」、Change Cipher Specは、クライアントが生成したものと同じになります。
- Client HelloとServer Helloに含まれていた324biteのランダム値と「プリマスタシークレット」を使って「マスタシークレット」を生成
- 「マスタシークレット」から「MACシークレット」と「セッション キー」を生成
- Finished:サーバーはFinished メッセージをクライアントに送ります。
このメッセージはChangeCipherSpecで決められた方法でサーバーから送られる最初の暗号化された通信です。クライアントはFinishedメッセージの内容をこれまでの手続き過程と照らし合わせ、正しいかどうか確認する必要があります。
- SSLハンドシェイクが完了し、セッションが開始されます。
クライアントとサーバーは「セッション キー」を使用して、相互に送信されるデータの暗号化と解読、および整合性の確認を行います。
楕円暗号サーバ証明書(ECDHE_ECDSA)のハンドシェイク
注:以下ではクライアントを認証を行わない手順について説明しています。
-
ClientHello:クライアントがサーバーに対して、サーバーとのSSL通信条件を決めるために必要な情報を送信します。それに加えて、クライアントが利用可能な楕円曲線名(ellipiptic_curves)とECポイント形式(ec_point_formats)を送信します。
クライアントがハンドシェイク条件を決めるために送信する情報
- クライアントが利用可能なSSL/TLSバージョン番号のリスト
- 利用可能なCipherSuiteのリスト
- クライアント日時の4biteにランダムな284biteの数値を加えた324biteのランダム値
- セッションID など
- クライアントが利用可能な楕円曲線名(ellipiptic_curves)
- ECポイント形式(ec_point_formats)
- ServerHello:サーバーは、ClientHelloのリストから選択し利用を決定した通信条件、楕円曲線名条件をクライアントに送信します。
サーバーが決定したハンドシェイク条件として送信する情報
- ClientHelloのリストから選択し利用を決定したSSL/TLSバージョン番号
- 決定したCipherSuite
- サーバー日時の4biteにランダムな284biteの数値を加えた324biteのランダム値
- セッションID など
- 決定した楕円曲線名(ellipiptic_curves)
- 決定したECポイント形式(ec_point_formats)
-
現在安全とされているSSL/TLSバージョン番号はTLSv1.2です。
- CipherSuiteは「鍵交換アルゴリズム」「認証アルゴリズム」「ストリーム暗号」「ハッシュアルゴリズム」を定義します。
- サーバーのランダム値はクライアントのランダム値と合わせてクライアントがマスターキーを生成するために利用されます。
- セッションIDはClientHelloによって異なったタイプになります。新規接続の場合は新しいセッションIDが作成されます。
セッション再開の場合はクライアントとサーバーのセッションIDは同一になります。
サーバーがセッションの再開を認めない場合はnull セッションIDとなります。すなわちセッションIDは送られません。
- クライアントとサーバー双方がが利用する楕円曲線名(ellipiptic_curves)とECポイント形式(ec_point_formats)が決定されます。
SSL/TLSバージョン番号、CipherSuiteについて、詳しくは以下を参照してください。
- Certificate:サーバーは自身の証明書を送信します。中間証明書等、証明書のチェーンがある場合はそれらの証明書も送付されます。
- ServerKeyExchange:サーバーは楕円曲線名とサーバーの公開鍵を署名付きで送ります。
- ServerHelloDone:サーバーは ServerHelloDone メッセージを送信し、Hello メッセージフェーズが終了したことを伝えます。
- ClientKeyExchange:クライアントはサーバーの証明書を検証し、認証を行います。認証の詳細手順は以下を参照してください。
サーバーを認証できない
発生した問題情報とともにハンドシェイクの失敗が、ブラウザ等に表示されます。
サーバーの認証に成功した場合
- クライアントは利用が合意された楕円曲線名(ellipiptic_curves)とECポイント形式(ec_point_formats)から、自身の公開鍵を作成しサーバーに送ります。
同時に、サーバーの公開鍵と自身の秘密鍵から「プリマスタシークレット」と呼ばれる共通鍵を作成します。
- 一方、サーバーはクライアントの公開鍵と自身の秘密鍵で「プリマスタシークレット」を作成します。楕円曲線暗号の原理から、クライアントの作成した「プリマスタシークレット」とサーバーが作成した「プリマスタシークレット」は一致します。この時点で、サーバーとクライアントだけが「プリマスタシークレット」を共有できたことになります。
- ChangeCipherSpec:クライアントは以下を生成し、クライアントからの通信を暗号化するための方法Change Cipher Specをサーバーに通知します。ここまでの通信自体は暗号化されていませんが、以降の通信は暗号化されます。
- Client HelloとServer Helloに含まれていた324biteのランダム値と「プリマスタシークレット」を使って「マスタシークレット」を生成
- 「マスタシークレット」から「MACシークレット」と「セッション キー」を生成
- Finished:クライアントはFinishedメッセージをサーバーに送ります。
このメッセージはChangeCipherSpecで決められた方法で送られる最初の暗号化された通信です。サーバーはFinishedメッセージの内容をこれまでの手続き過程と照らし合わせ、正しいかどうかを確認する必要があります。
- ChangeCipherSpec:サーバーも以下を生成し、サーバーからの通信を暗号化するための方法Change Cipher Specをサーバーに通知します。ここまでのサーバーからの通信は暗号化されていませんが、以降の通信は暗号化されます。
サーバーの作成した「マスタシークレット」、「MACシークレット」、「セッション キー」、Change Cipher Specは、クライアントが生成したものと同じになります。
- Client HelloとServer Helloに含まれていた324biteのランダム値と「プリマスタシークレット」を使って「マスタシークレット」を生成
- 「マスタシークレット」から「MACシークレット」と「セッション キー」を生成
- Finished:サーバーはFinishedメッセージをクライアントに送ります。このメッセージはChangeCipherSpecで決められた方法でサーバーから送られる最初の暗号化された通信です。クライアントはFinishedメッセージの内容がこれまでの手続き過程と照らし合わせ正しいかを確認する必要があります。
- SSLハンドシェイクが完了し、セッションが開始されます。
クライアントとサーバーは「セッション キー」を使用して、相互に送信されるデータの暗号化と解読、および整合性の確認を行います。
クライアント(ブラウザ等)のSSLサーバー証明書検証手順
クライアント(ブラウザ等)は以下の手順でSSLサーバー証明書を検証し、サーバーが意図した接続先であることを確認します。
-
SSLサーバ証明書が現在日時で有効かを検証します。
SSLサーバー証明書の有効期限に現在の日時が含まれていない場合
クライアントは検証を中止しエラーを通知します。
有効であることを確認できた場合
次の手順に進みます。
-
クライアントはSSLサーバ証明書のチェーンをさかのぼり、その証明書のroot証明書(CA 認証局の証明書)が何かを確認し、見つかったroot証明書(CA 認証局の証明書)がクライアントシステムの信頼できるroot証明書リストに含まれているかを検証します。
リストに含まれていない場合
「信頼できない証明書」エラーを表示し検証を中止します。
信頼できるroot証明書に基づいて発行された証明書であることが確認できた場合
次の手順に進みます。
-
SSLサーバ証明書には証明書の認証局(CA)が行った署名(signature)が含まれています。
クライアントは認証局(CA)の公開鍵を使って、署名(signature)を検証します。
偽装された証明書の場合
検証は失敗します。また、署名(signature)に利用された認証局(CA)の秘密鍵と、検証に利用される認証局(CA)の公開鍵が一致しない場合も検証は失敗します。
署名が検証可能な場合
信頼のチェーンが成立し、SSLサーバー証明書の記載内容が信頼できます。
-
クライアントはサーバー証明書に記載されているホスト名と、実際に接続しているホスト名が一致するかをチェックします。これまでの過程で証明書が有効であることが検証済みであっても、この検証を経ないと安全なhttps接続は確保できません。
検証を行わないと中間者攻撃などが可能になってしまいます。
一致しない場合
ブラウザは証明書とホスト名が不一致の警告を出します。メールクライアントの場合、この検証を行わないこともあります。
-
以上が完了すると、クライアントとサーバーの安全な接続が確立されます。