シェルスクリプトマガジン

もしインターネットの1秒が1年だったら 第2回(vol.48掲載)

3月9日  午後7時27分  ClientHello送信

サーバーちゃんとのやり取りに暗号を使うことを決めたクライアントちゃんですが、具体的にどんな暗号を使えばいいのかはまだわかりません。クライアントちゃんはこう見えて暗号の達人なので、何種類もの暗号を駆使することができるのですが、相手と文通する以上、クライアントちゃんとサーバーちゃんが共通に理解できる暗号で会話しないといけません。
TLSそのものは暗号を行う方式ではなく、別に定められた暗号方式を使って通信を行うための仕組みです。そのため、TLSハンドシェイクではこの暗号方式を決めることがコアになります。
暗号というものは時間が経つにつれて、その弱点が明らかになったり、コンピューターの性能向上とともに解読に必要な時間が短くなったりして弱くなります。そのため、情報セキュリティにおいて暗号を利用する際には、使用する暗号方式を新しい物に移行できることが重要になります。
TLSは将来開発しうる暗号方式を受け入れる事ができる、一種のフレームワークとして設計されています。
今回はクライアントちゃんとサーバーちゃんとで暗号通信を行いますが、当然ながらお互いに使える暗号方式は限られており、事前にそれらはわかりません。TLS ではこの暗号方式を後述するCipherSuiteと呼ばれる16bitの識別子で取り扱います。ClientHelloではクライアントが使うことができる好みのCipherSuiteのリストをサーバーに送ります。
他にもバージョン番号や、セッション再開(resumption) やmaster secret 生成に使用する乱数、使用できる署名及びアルゴリズムのリストなどが送信されます。
クライアントちゃんは、サーバーちゃんとの通信に暗号を使いたいという話と、自分がマスターしている暗号のリストを書いた手紙をサーバーちゃんに送りました。手紙の書き出しは、もちろん「ハロー」です。
クライアント側のハンドシェイクはACKパケットを送信した3月9日の段階ですでに完了しているので、これは3月16日にサーバーちゃんがクライアントちゃんからのACKパケットを受け取る前の話になります。

CipherSuite:
CipherSuiteとは鍵交換アルゴリズム(Key Exchange)、暗号アルゴリズム(Cipher)、メッセージ認証符号(MAC) の組み合わせであり、16bitの識別子が割り振られています。例えばTLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384は鍵交換にECDHE_RSA、暗号にAES_256_GCM、メッセージ認証符号にSHA384を使用することを示しています。

master secret
ある意味ではハンドシェイクの成果物とも言える、通信当事者以外には秘密でありながら、通信当事者同士で共有された値です。長さは48バイトであり、同じく秘密に共有されpremastersecretと、Helloで交換した乱数から擬似乱数関数(PRF)を用いて生成されます。擬似乱数関数はTLSではハッシュ関数の様な使い方をする関数であり、入力から出力が一意に定まるが、出力から入力を予測することは不可能な関数です。

 

 

3月19日  午前10時30分  ClientHello 受信

それから10日後、世間ではそろそろ冬休みが始まる頃に、クライアントちゃんからの通信がサーバーちゃんのもとに届きました。
クライアントちゃんからの3日ぶりの手紙を喜び勇んで開封すると、中にはサーバーちゃんとのやり取りに暗号を使いたいという内容が書かれています。
実を言うと、わざわざ443番ポートに向けて手紙を送ってきた時点で予想はしていました。サーバーちゃんも暗号にはそれなりに精通している自信があるので、手紙に書いてある暗号リストの中から、自分が使える暗号でもっとも難しい暗号を選びます。今回、サーバーちゃんは先ほど例に挙げたTLS_ECDHE_RSA_WITH_AES_256_GCM_ SHA384
を選択しました。
ClientHelloを受信したサーバーは、その中のCipherSuiteのリストや署名、およびハッシュアルゴリズムのリストから、実際に使用する方式を選定します。この選定方法はアプリケーションによって異なり、管理者が自由に設定を行えます。

 

3月20日 午後7時20分 ServerHello, Certificate, ServerKeyExchange送信

サーバーちゃんは自分が選択した暗号を書いて、翌日の晩にはクライアントちゃんに返事を書きました。一日待つ必要があったのは、その他に証明書を用意したり署名をしたりといった、暗号通信に必要ないろいろな手続きが必要なためです。
TLSにおけるサーバーからのこの返答は複数のメッセージで構成されることがあります。ServerHelloでは実際に使用するCipherSuiteとセッション再開やmaster secret生成に使用する乱数などの情報を送ります。
Certificateではサーバー証明書、及びその証明書を検証するために必要な証明書をクライアントちゃんに送ります。この証明書は先に決定したCipherSuiteで使えるものでなければなりません。運用上、実際には証明書の方を認証局から発行してもらい、簡単にいじれるものではないため、証明書に適合したCipherSuiteを選ぶことになります。このCertificateは任意ですが、これを送らないということは、通信先であるサーバーが、本当に想定されるサーバーなのかの手がかりを与えない、匿名な通信となります。暗号通信において、通信相手が攻撃者などではなく、意図した通信相手であることを保証することは重要です。
ServerKeyExchangeでは公開鍵や署名をクライアントちゃんに送ります。具体的なデータ内容などはCipherSuiteで指定した鍵交換アルゴリズムによって異なります。このServerKeyEx-changeは任意であり、単純なRSA のようにCertificateに公開鍵や署名を含む場合にはこのメッセージは送られません。しかしながら、この公開鍵が署名と一体であるということは、すべての通信でこれを使いまわしているということであり、安全性に疑問が残ります。将来的に公開鍵とセットである秘密鍵が破られた際に、後から秘匿性が失われる恐れがあります。そのため、鍵を使い捨てにして前方秘匿性(forward secrecy)を確保することができる、DHE等のアルゴリズムが推奨されています。この使い捨ての鍵を証明書とは別に送信する際にServerKeyExchangeは使われます。
最後にServerHelloDoneを送ることで、返事を終わらせます。

3月 31日 午後10時26分ServerHello, Certificate, ServerKeyExchange受信

もうまもなく新年度が始まろうとするときに、サーバーちゃんから証明書などが届きます。
サーバーちゃんから届いた情報を元に証明書の検証を行い、通信相手が間違いなくサーバーちゃん自身であることを確認します。そして、ここで初めてサーバーの公開鍵が手に入ります。公開鍵暗号において、暗号化に必要なのは相手の公開鍵なので、裏を返せばここまでの通信内容はすべて暗号化されていない平文の状態で行われていたということです。この暗号化されていないハンドシェイク部分は度々脅威にさらされてきました。最近で言えばOpenSSL のCVE-2015-0204(FREAK)
という脆弱性は、このハンドシェイク時に中間者攻撃により脆弱な暗号化方式に切り替えさせられ、通信の機密性を脅かすというものでした。
その後、サーバーに送るための公開鍵を用意します。公開鍵を生成するにあたり、暗号論的な安全性を持った乱数を用いて秘密鍵を生成し、指定されたCipherSuiteに従って公開鍵を生成し、次のメッセージに載せます。そして、自身はその自分の秘密鍵と受け取った公開鍵からpremastersecretを求めます。(Diffie-Hellman等) これによりmaster secretをクライアント側で用意できるようになります。master secretを用意したらpremaster secretはすぐに抹消します。もしこの2 人のお便りを盗み見してる人に、premaster secretが漏れてしまえば、そこからmastersecretが計算できるので、あっという間に秘密が破られてしまうからです。
手紙に含まれてる情報をもとに、クライアントちゃんはmaster secretを生成しました。長い長いやり取りのあとに手に入れた、初めての2人だけの秘密です。クライアントちゃんにとってそれは単なる48バイトのデータの羅列ではなく、いつでも傍にサーバーちゃんの面影を感じることができる、大切な大切なデータです。

4月1日 午前9時39分 ClientKeyExchange, ChangeCipherSpec, Finished送信

翌朝、クライアントちゃんはサーバーちゃんとの秘密のやり取りに初めて取りかかります。エイプリルフールですが、クライアントちゃんはサーバーちゃんに嘘なんてついたりしません。第一、この手紙が相手に届く頃にはエイプリルフールなんて忘れられています。きっと。ClientKeyExchangeでは、自分が使用する公開鍵などを送ります。RSAの場合にはpremas-ter secretを暗号化して送りますが、通常良く使われるDiffie-Hellmanやその派生では、その公開鍵を交換することでpremaster secretが計算可能です。
ChangeCipherSpecは次からハンドシェイクの結果に基づき、暗号化したデータを送るというメッセージであり、いよいよ次から暗号化したデータに突入します。
Finishedは暗号化された最初のメッセージです。と言っても、データ本体を暗号化するCipherSuiteで指定された、例えばAES のような暗号化ではなく、きちんとハンドシェイクが成功したかを検証するためのverify_dataを送ります。このverify_dataはmaster secretとこれまでのハンドシェイクメッセージから擬似乱数関数を通すことで生成され、通信が改竄されていなければサーバーはこれを検証することができます。
master secretを手に入れたクライアントちゃんは、サーバーちゃんへの手紙を試しに暗号で書いてみました。ちゃんとサーバーちゃんは書いてあることを理解してくれるでしょうか?

4月9日 午前8時10分 ClientKeyExchange, Change CipherSpec, Finished 受信

クライアントちゃんの公開鍵とともに、初めての秘密のお便りが届きました。もう、秘密のコネクションの確立は目前です!
サーバーは受け取った公開鍵と、自分が送った公開鍵に対応する秘密鍵からpremaster secretを求めます。この値は鍵交換アルゴリズムの性質からクライアントと同じものになっているはずです。もしそうでなければお便りは輸送路のどこかで改竄されています。そして、そこからmaster secretを計算し、クライアントと同様にpremaster secretは抹消します。
その後、暗号化されたFinishedの中身をTLSで定められた手法でサーバーも試しに生成してみて、送られてきたものと一致していることを確認します。もし一致してなければその通信は危険な状態に晒されていることになります。fatalレベルのアラートを送って通信を切断します。
サーバーちゃんはクライアントちゃんからの暗号文を自慢の暗号力で読み解き、正しく復元できることを確認、誰にも知られることなくmaster secretが2人の間で共有されました。これで鍵交換成功です!

 

「いみ つうじる」から「」を抜いて、「いみつうじる」ね!

4月9日 午後3時10分 NewSessionTicket, Change CipherSpec, Finished送信

さて、サーバーちゃんもきちんと検証用の情報を送り、ハンドシェイクに成功したことをクライアントちゃんに伝えます。ここからはサーバーちゃんも手に入れたmaster secretで手紙を暗号化し、2人だけにしかわからない秘密のやりとりが始まります。
NewSessionTicketでは、セッション再開に必要な、サーバーが持っているべき情報を、クライアントに暗号化した状態で持ってもらうための情報です。実はハンドシェイクの冒頭のHelloで、お互いにTLS Session Resumption without Server-Side Stateを利用するかどうかの情報が交換できます。もしお互いにこれを利用できるのであれば、セッション再開情報をサーバーが持たずに、このチケットという形でクライアントに持ってもらい、再開時にサーバーがそれを受け取り復号化して、セッションを再開できます。が、今回は1回しか通信を行わないので、セッション再開の話はなしにしましょう。
ChangeCipherSpecとFinishedはクライアントと同じような流れです。ちょっと擬似乱数関数に入れる情報が違うだけです。

4月19日 午前5時49分 NewSessionTicket, Change CipherSpec, Finished受信

TLSハンドシェイク開始から42日が経過しました。早朝サーバーちゃんから届いたハンドシェイク最後の手紙によって、クライアントちゃんもハンドシェイクの成功を確認できる時が来ました。
セッション再開用のチケットを引き出しにしまいつつ、送られてきたデータを検証します。これで正常な通信の確立が確認できたらいよいよ暗号通信の始まりです。
TLS によってロスした42日という時間は、実時間に直すと110ミリ秒です。TLSハンドシェイクは必ずサーバーとクライアントの間を2往復する必要があるため、この時間はクライアントとサーバーの距離によって大きく左右されます。HTTPSを導入する場合は、keep-aliveによるコネクションの再利用や、CDNによる通信距離の改善などを検討したいものです。

「この続きはシェルマガvol.49、またはオリジナル版掲載サイトを見てねっ!」

本記事掲載のシェルスクリプトマガジンvol.48は以下リンク先でご購入できます。