TLS1.3 通信の手順の整理は、基本的には https://tls13.xargs.org から翻訳されました。元の文書を参照することをお勧めします。
クライアント:鍵ペアの生成#
(client_priv, client_pub) として記述します。
クライアント:クライアントハローパケットの平文送信#
主な内容は次のとおりです。
- ランダムなクライアントランダム
- クライアントがサポートする暗号スイート
- クライアントがサポートするプロトコルバージョン
- 要求されたサーバー名 SNI(Server Name Indication)
- PSK(pre-shared-keys)プリ共有鍵モード
- Key Share 公開鍵リスト(client_pub)
- セッションチケット
- 圧縮方法など...
SNI フィールドにより、サーバーは同じ ipグループで複数の TLS サービスを提供できます。ハンドシェイクプロセス中に、SNI に基づいて対応する証明書を返します。
Key Share 拡張は、クライアントがサーバーが受け入れる可能性が高い公開鍵と暗号アルゴリズムの 1 つ以上を送信します。サーバーが受け入れる場合、Server Hello の後続のデータは暗号化されて転送されます。事前にキーエクスチェンジが行われるのと同じです。サーバーが受け入れられない場合は、再試行のために Retry Hello Request メッセージが返されます。
セッションチケットは、接続が確立された後にサーバーから送信され、クライアントは再接続のためにこのデータを保存できます。
PSK の使用方法については、When do clients use TLS in PSK mode?を参照してください。
サーバー:鍵ペアの生成#
(server_priv, server_pub) として記述します。
サーバー:サーバーハローパケットの平文送信#
主な内容は次のとおりです。
- ランダムなサーバーランダム
- 暗号スイートの選択
- 公開鍵の選択
- プロトコルバージョンの選択
- Key Share(server_pub)の返却
- 圧縮方法など...
サーバー:ハンドシェイクキーの計算#
以下の情報を使用してハンドシェイクキーを計算します。
- Client Hello Packet から取得した client_pub
- サーバーが生成した server_priv
- SHA384 (ClientHello + ServerHello) で送信されたメッセージのハッシュ値を計算します。
以降のハンドシェイクプロセスは、このキーを使用して暗号化されます。
クライアント:ハンドシェイクキーの計算#
以下の情報を使用してハンドシェイクキーを計算します。
- Server Hello Packet から取得した server_pub
- クライアントが生成した client_priv
- SHA384 (ClientHello + ServerHello) で送信されたメッセージのハッシュ値を計算します。
以降のハンドシェイクプロセスは、このキーを使用して暗号化されます。
サーバー:証明書の暗号文送信#
サーバーは、Client Hello で指定された SNI に基づいて証明書を返し、検証を行います。
証明書の検証と発行#
- サーバーは自分自身の鍵ペア(host_priv、host_pub)を生成し、host_pub とドメイン情報、地域情報などを組み合わせて host_info を CA(証明書機関)に送信します。
- CA は申請者情報を審査し、自身の秘密鍵 CA_priv を使用して hash (host_info) を暗号化して署名 SIG を生成し、最終的に SIG と host_info を証明書としてサーバーに発行します。
- クライアントはサーバーから証明書を取得した後、インストールされている CA の公開鍵を使用して署名 SIG を復号化し、元のデータ CA_pub (SIG) を取得します。
- クライアントは証明書から host_info を取り出し、hash (host_info) を自分で計算し、検証と復号化されたデータが一致するかどうかを確認します。
信頼チェーン#
一部の場合、証明書はサブ CA によって発行される場合があります。クライアントが証明書を要求すると、サーバーは中間証明書と自身の証明書を一緒に返します。
- クライアントはまず、インストールされている CA の公開鍵を使用して中間証明書を検証し、中間証明書の公開鍵を取得します。
- クライアントは次に、中間証明書の公開鍵を使用してサーバー証明書を署名検証します。
サーバー:証明書の検証のための暗号文送信#
前の手順により、クライアントは証明書(およびその中の公開鍵)が現在の要求されたサービス名に属していることを確認できますが、このサーバーがこの証明書の所有者であることを証明することはできません。したがって、サーバーは証明書が発行される前に作成した秘密鍵 host_priv を使用してハンドシェイクメッセージの要約を暗号化してクライアントに返します。クライアントは証明書の host_info から公開鍵 host_pub を取り出し、このデータを復号化してハンドシェイクメッセージの要約を自分で計算し、一致するかどうかを比較します。これにより、クライアントはこの接続のセキュリティを確認できます。
サーバー:ハンドシェイク終了検証メッセージの暗号文送信#
サーバーはハンドシェイク段階のすべてのメッセージをハッシュして検証メッセージとしてクライアントに送信します。
サーバー:アプリケーションキーの計算#
サーバーは、Handshake Key と Client Hello からサーバーハローまでのすべての情報をハッシュしてアプリケーションキーを計算します。これは、データ転送段階での対称キーです。
クライアント:アプリケーションキーの計算#
クライアントは同じ方法でアプリケーションキーを計算します。
クライアント:ハンドシェイク終了の暗号文送信#
クライアントはハンドシェイク段階のすべてのメッセージをハッシュして検証メッセージとしてサーバーに送信します。
これにより、クライアントとサーバー間で Application Key を使用して対称暗号化通信が行われます。
サーバー: Session Ticket 1 の暗号文送信#
サーバーはクライアントに対して Session Ticket を提供し、新しいセッションを迅速に開始するために計算とネットワーク遅延を大幅に削減します。以下を含みます。
- Ticket Lifetime 有効期間
- Ticket Age Add(各チケットごとに異なる)
- Ticket Nonce ランダムな値(各チケットごとに異なる)
- Session Ticket
Ticket Age Add
は、サーバーが生成するランダムなミリ秒数です。クライアントは Session Ticket を使用して接続を復元する際に、ticket_age(Session Ticket を受け取ってから現在までの時間差を表す)にこの値を加えて混乱させる必要があります。サーバーはこの値を受け取り、クライアントの ticket_age と自身の計算した時間差が近いかどうかを検証し、一定の閾値を超える場合はこの接続を直接拒否できます。これにより、Session Ticket の再利用によるリプレイ攻撃をある程度防ぐことができます。
サーバー: Session Ticket 2 の暗号文送信#
クライアント(たとえばブラウザ)は通常、複数の接続を送信し、各 Session Ticket は 1 回のみ使用できるため、サーバーは通常、複数の Session Ticket を返します。
参考文献:
RFC8446
xargs.org - TLS
xargs.org - x25519
Wikipedia - Shared_secret
Wikipedia - Pre-shared_key
Wikipedia - SNI
A walkthrough of a TLS 1.3 handshake
一文详解 HTTPS 与 TLS 证书链校验
SSL/TLS 协议详解 (中)—— 证书颁发机构
网络安全科普:奇妙的 SSL/TLS 证书(基础篇)