TLSハンドシェイクの流れを分かりやすく説明

セキュリティ

TLSは暗号、認証、改ざん検出の機能があり、ネットワークセキュリティとしては必須技術です。
本書ではTLSの仕組みを解説し、理解を深めていきます。
TLSはいくつかバージョンがありますが、本書はTLS1.3に特化した説明となっています。

SSLとの関係

SSLはよくTLS と一緒に出てきますが、SSLはTLSの前身であり今はあまり使われないです。
SSLは1995年にNetscapeが開発したインターネット通信を暗号化する仕組みです。
後継であるTLSはIETFによる標準化がされています。

TLSハンドシェイク

TLSはクライアントとサーバとが通信をするときに様々なやり取りをします。

ハンドシェイク「握手」という意味の英単語で、TLSではクライアントとサーバがお互いの状態や設定を確認して安定した接続を確立するための握手に例えられています。

接続開始時の大まかな流れ

TLSは大まかに次の2ステップの流れになっています。
 【STEP1】データの暗号化に使う共通鍵を生成(鍵交換)
 【STEP2】サーバ証明書で正しいサーバであることの確認

クライアント認証はオプション(省略可)とされていますので、今回の例では、サーバー認証だけを行っています。

TLS1.3に特化した説明となっています。

【STEP1】データの暗号化に使う共通鍵を生成(鍵交換)

Client Helloメッセージ
最初にクライアントは次の処理をします。

  • 秘密鍵を生成します。
  • 秘密鍵(ランダムな値)と、サーバで共有する数字(事前に規格で決まっている)をもとに公開鍵を生成します。
  • 対応可能な暗号スイート(暗号やハッシュ規格)、対応な鍵交換規格の候補、先ほど生成した公開鍵をサーバへ送付します。


■Server Helloメッセージ
サーバはクライアントからの送信を受け取った後、次の処理をします。
①と②はクライアントと同じですが、秘密鍵と公開鍵の値はクライアントと異なります。

  • 秘密鍵を生成します。
  • 秘密鍵(ランダムな値)と、サーバで共有する数字(事前に規格で決まっている)をもとに公開鍵を生成します。
  • クライアントからの対応な暗号スイート、鍵交換規格の候補を選んだ結果と、先ほど生成した公開鍵をサーバへ送付します。

なお、TLS1.3での鍵交換は一般的にECDHEが良く使われます。
ECDHEは楕円曲線暗号を使用することで、短かい鍵長で高い安全性を実現し、処理速度が速いのが特徴です。


クライアントとサーバはそれぞれ受け取った公開鍵、両者で共有する数字、自分の秘密鍵の3つを使って、共通鍵を生成します。
この共通鍵は両者で同じ値になります。

クライアントとサーバで今回の通信で使う共通の鍵が共有できたので、この後の通信はこの鍵を使って暗号化がされます。

【STEP2】サーバ証明書で正しいサーバであることの確認

■Certificate
サーバの公開鍵証明書が正当なものか確認します。
サーバはサーバ証明書(公開鍵証明書)をクライアントへ送り、クライアントはCAの公開鍵で正当性を確認します。
ここで使われている技術はPKI(公開鍵基盤)による確認となります。

Certificate Verifyメッセージ
サーバが公開鍵に対する秘密鍵を確かに持っていることを確認するために、サーバは署名をクライアントへ送り、クライアントはサーバの公開鍵を使って署名を検証します。

  • サーバは、ハンドシェイク全体のこれまでのやり取りのハッシュ値を計算
  • そのハッシュ値に対して サーバ証明書に対応する秘密鍵で署名 を作成
  • その署名を Certificate Verify メッセージ としてクライアントへ送る
  • クライアントはサーバ証明書の「公開鍵」でCertificate Verify メッセージを復号し、これまでのやり取りのハッシュ値と一致することをかくにn

PSKによるセッション再開

クライアントとサーバ間でタイムアウトが発生した場合、セッションを再開しますが、また1から鍵交換、サーバ認証全てをやり直すのではなく、予め共有してあるPSKを使って速やかに再開できます

PSKはSession Ticketという情報の中に格納され、Session Ticketは暗号化してクライアント側で保持するので安全です。

Session Ticketはサーバが予め用意しているTicket Keyという鍵で複合化して使います。

最初の接続時(新しいフルハンドシェイク)

  • クライアントがClientHelloを送信
  • サーバがフルハンドシェイクを完了後、セッション再開に必要な情報(PSK、識別子、有効期限など)をSession Ticketとして生成
    Ticket KeyでSession Ticketを暗号化してクライアントへ送信
    ※Session Ticketを暗号する際はAEAD(認証付き暗号化)を使用する
    ※サーバはクライアントへ送信した後、Session Ticketは削除する。(サーバー側のリソースが消費を防ぐため)
  • クライアントはSession Ticket(暗号化されたまま)を保持しておく

PSKを使ったセッション再開

  • クライアントがSession Ticket(暗号化されたまま)、ECDHE鍵共有(key_share extension)を含めてサーバへ送信
  • サーバは受け取ったSession TicketをTicket Keyで復号し、PSKなどの情報を取り出して検証
  • サーバはクライアントのECDHE鍵共有(key_share extension)とサーバのECDHE鍵共有(key_share extension)からトラフィックキーを生成
  • サーバは、サーバ側の鍵共有(ECDHE)を返す
  • クライアントは受信した鍵共有(ECDHE)から暗号化通信に必要な鍵(トラフィックキー)を算出する。
  • クライアントはFinishedメッセージを送る
  • サーバはFinishedメッセージを送る
  • 以降はトラフィックキーで暗号化してやり取り

まとめ

  • TLS1.3 ハンドシェイクの流れ
    • 【STEP1】 共通鍵を作る:クライアントとサーバが公開鍵を交換して、同じ共通鍵を計算する
    • 【STEP2】サーバを確認する:サーバは証明書を送り、正しいサーバかをクライアントがチェックする
  • セッション再開(PSK方式)
    • 初回接続のとき、サーバは Session Ticket をクライアントに渡す
    • 再接続のとき、クライアントは Ticket を送り返す
    • サーバは Ticket を復号して PSK(事前共有鍵) を取り出す
    • PSKを使ってすぐに新しい鍵を作り、暗号通信を再開できる

コメント

タイトルとURLをコピーしました