今回は、TLSで暗号化通信を開始する際のメッセージフローを見ていこう。SSL/TLSでは通信の開始時、Handshake Protocolによって、暗号化通信を開始するために必要な各種パラメータのネゴシエーションが行われる。このネゴシエーションでは、クライアントからのClient Hello〜Finishedを送出するまでの間、さまざまなメッセージの交換を行うのだが、それには2つのパターンがある。1つは「新規セッションを確立して通信を開始する」パターン、もう1つが「既存セッションに基づいて通信を開始する」パターンだ。最初に前者について説明しよう。
図33は「新規セッションを確立して通信を開始する」場合の典型的なメッセージのやりとりを示したものだ。図中、実線は必須のメッセージを、点線はオプションのメッセージを表している。
ここでいう「新規セッションを確立して通信を開始する」とは、一切の予備知識を使用することなく、暗号化通信を開始するために必要なすべてのパラメータを、全くゼロから設定してゆくという意味だ。では、図中の主要なメッセージをピックアップして、そこでやりとりする情報に注目しながら、ネゴシエーションの流れを説明しよう。
1. 最初にクライアントは、Client Helloメッセージの中に自身が利用可能な暗号化アルゴリズムと圧縮アルゴリズムの一覧、およびクライアントランダム値を格納。それをサーバへ送信する。このとき一覧はクライアント自身が利用したい順に並べておく
2. Client Helloを受け取ったサーバは、メッセージに含まれる暗号化アルゴリズムと圧縮アルゴリズム一覧の中から、自身も利用可能なものを見つけ出し、そのいずれを利用するかを決定する。利用を決定した暗号化アルゴリズムと圧縮アルゴリズムは、サーバランダム値とともにServer Helloメッセージに格納してクライアントへ通知する
【状況】
この段階で、サーバとクライアント間では、利用する暗号化/圧縮アルゴリズムについて合意が成立するとともに、サーバランダムとクライアントランダムについておのおのの情報を共有する状況が出来上がる
3. 続くプリマスタシークレット(各セキュリティパラメータのタネとなる情報)の送付を安全に行うため、サーバはクライアントに対して、サーバの証明書をServer Certificateメッセージに格納して通知する。また、サーバが証明書を持っていない場合や、サーバの証明書が署名にしか使えない場合は、Server Key Exchangeメッセージを使って、RSA公開キーやDiffie&Hellman公開情報を通知する
4. クライアントは各暗号パラメータのタネとなるプリマスタシークレット(図26)を生成する。この情報はサーバとの間で共有し、各パラメータのタネとして利用する機密度の高い重要な情報である。これをサーバに通知するに当たっては、その内容が第三者に知られないよう安全に行う必要がある。だが、この段階ではまだrecordレイヤは機能しておらず、送信内容は全く暗号化されていない。そのため何らかの方法で安全性を確保しなければならない
ここで重要になるのが、Server Certificateメッセージで送付されたサーバの公開キーである。キー交換に使用するアルゴリズムがRSAの場合には、プリマスタシークレットをサーバの公開鍵で暗号化し、その暗号化された情報をサーバに送信する。サーバは自分の秘密鍵で復号、プリマスタシークレットを知ることができる。またDiffie&Hellmanを使う場合には、クライアントの公開情報をそのままプリマスタシークレットとして通知する。
【状況】
この段階では、サーバとクライアント間において、利用アルゴリズム、サーバランダム、クライアントランダム、プリマスタシークレットを共有した状態が確定する。これら要素が確定すると、サーバ、クライアントともに、暗号化通信に必要な各種パラメータを生成可能となる(図25)。両者は、クライアントMAC書き込みシークレット、サーバMAC書き込みシークレット、クライアント書き込みキー、サーバ書き込みキー、クライアント書き込みIV、サーバ書き込みIVを生成し、その情報に基づいてペンディングステートのセキュリティパラメータを設定する(図24)
5. ペンディングステートへのセキュリティパラメータ設定が終了したら、クライアントはChange
Cipher Spec Protocolメッセージを送出する。これにより、クライアントの書き込みカレントステートには、書き込みペンディングステートの内容がコピーされ、先ほど合意した新しい暗号化仕様による通信が始まる
6. こうして利用を開始した新しい暗号化仕様の動作を最初に確認するのが、Finishedメッセージである。クライアントでは、Finishedメッセージにクライアントとサーバの両者が知っている情報を格納しサーバへ送出する。このときすでにrecordレイヤでは新しい暗号化仕様での動作が開始されているので、Finishedメッセージはそれに基づいて暗号化してから送出される
Finishedメッセージを受信したサーバは、それを新しい暗号化仕様に基づいて復号する。そしてサーバ自身が知っている情報と照合する。そこで内容が一致すれば、サーバ〜クライアント間で新しい暗号化仕様が正常に合意したことになる。
7. 同様にしてサーバもクライアントにChange Cipher
Spec Protocolメッセージを送出する。これによりサーバの書き込みカレントステートには、書き込みペンディングステートの内容がコピーされ、先ほど合意した新しい暗号化仕様による通信が始まる
8. やはり同じようにサーバはFinishedメッセージを送出し、クライアントにおいてメッセージ内容の照合を行う。内容がクライアントの持つ情報と一致すれば、サーバ−クライアント間で新しい暗号化仕様が正常に合意したことになる
サーバ〜クライアント間で、暗号化仕様のネゴシエーションは、一般的にはこのような手順により行われる。また、サーバとクライアントの構成や、サービス内容によっては、メッセージフローに示したオプションメッセージを利用する必要も出てくるが、ここではその具体的なフローについては省略する。
2つ目のパターンは「既存セッションに基づきコネクションを設定」する方法だ。すでに設定されたセッション情報を再利用することで、セッション確立のための情報量を減らし、素早くコネクションを用意できる。もう少し具体的にいえば、図22に示したセッション内部情報に関して、既存のものをそのままコピーして利用しようというアイデアである。
図34はメッセージシーケンスの例だ。このときのメッセージシーケンスは、基本的に新規セッションを確立する場合のシーケンスから、暗号化仕様の合意を形成する部分をすべて省略した形のサブセットとなっている。
1. サーバに対する接続要求もClient Helloメッセージを使用する。新規の場合と異なるのは、Client Helloメッセージに再利用するセッションのセッションID、そのセッションで使用する暗号化/圧縮アルゴリズムを格納する点である
2. サーバが指定した既存セッションが有効で、サーバがその利用を認める場合、サーバは当該セッションID、そのセッションで使用する暗号化/圧縮アルゴリズムを、Server Helloメッセージに格納してクライアントに返送する
また、サーバがセッションの再利用を認めないときには、新たに割り当てたセッションIDを格納してクライアントに返送する。この場合、クライアントは新規セッション設定に準ずる手順で、必要な暗号化仕様のネゴシーエションを実行する必要がある。
【状況】
セッションの再利用が確定すると、その時点で暗号化通信に必要なパラメータはすべてそろったことになる。つまり、これ以外に暗号化仕様を合意するためのネゴシエーションは行われない
3. クライアントはChange Cipher Spec Protocolメッセージを送出して、指定したセッションに基づく暗号化仕様による通信を開始する
4. クライアントはFinishedメッセージを送出して、サーバとの間で合意した暗号化仕様が正常であることを確認する
5. 同様にサーバはChange Cipher Spec Protocolメッセージを送出して、指定したセッションに基づく暗号化仕様による通信を開始する
6. 続いてサーバはFinishedメッセージを送出し、クライアントとの間で合意した暗号化仕様が正常に利用できることを確認する
既存セッションを再利用する場合、これだけのステップで暗号化通信が開始できる。図からも一目瞭然だと思うが、クライアント〜サーバ間でやりとりするメッセージは大幅に減る。そのため、コネクション確立のコストを低く抑えることが可能となる。
Copyright © ITmedia, Inc. All Rights Reserved.