TLS1.3 通信流程梳理,基本是从 https://tls13.xargs.org 翻译过来的,建议看原文
客戶端:生成密鑰對#
記作 (client_priv, client_pub)
客戶端:明文發送 Client Hello 封包#
主要包含以下內容:
- 隨機數 client_random
- 客戶端支援的 cipher suites
- 客戶端支援的協議版本
- 請求的伺服器名稱 SNI (Server Name Indication)
- PSK (pre-shared-keys) 預共享密鑰模式
- Key Share 公鑰列表 (client_pub)
- Session Ticket
- 壓縮方式等...
SNI 欄位使伺服器可以在同一個 ip 組上提供多個 TLS 服務,在握手過程中根據 SNI 返回對應的憑證。
Key Share 擴展會發送一個或多個客戶端認為服務端很可能會接受的公鑰及加密演算法,如果服務端接受,則 Server Hello 後續的資料可以加密傳輸。相當於提前進行了 Key Exchange 如果服務端不能接受則返回一個 Retry Hello Request 訊息重新進行握手。
Session Ticket 在連接建立完成後由服務端發送,客戶端可以保存此資料用於後續快速恢復重連。
PSK 的使用參考 When do clients use TLS in PSK mode?
服務端:生成密鑰對#
記作 (server_priv, server_pub)
服務端:明文發送 Server Hello 封包#
主要包含以下內容:
- 隨機數 server_random
- 選定一個 cipher suite
- 選定一個 public key
- 選定協議版本
- 返回 Key Share 包含 (server_pub)
- 壓縮方式等...
服務端:計算 Handshake Key#
通過以下資訊計算握手密鑰:
- client_pub 從 Client Hello 封包中獲得
- server_priv 由服務端生成
- SHA384 (ClientHello + ServerHello) 計算之前發送的訊息的雜湊值
後續的握手過程都通過此密鑰加密
客戶端:計算 Handshake Key#
通過以下資訊計算握手密鑰:
- server_pub 從 Server Hello 封包中獲得
- client_priv 由客戶端生成
- SHA384 (ClientHello + ServerHello) 計算之前發送的訊息的雜湊值
後續的握手過程都通過此密鑰加密
服務端:密文發送憑證#
服務端根據 Client Hello 中指定的 SNI 返回憑證並進行校驗
憑證的校驗與簽發#
- 服務端生成自己的密鑰對 (host_priv, host_pub) 並將 host_pub 和域名資訊地域資訊等組合成 host_info 發送給 CA (Certificate authority)
- 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 解密此資料,再自行計算握手訊息摘要進行比對是否一致。至此客戶端可以確認此連接的安全性
服務端:密文發送握手結束驗證訊息#
服務端將握手階段的所有訊息取雜湊作為驗證訊息發送給客戶端
服務端:計算 Application Key#
服務端通過 Handshake Key 和從 Client Hello 到服務端握手結束的所有資訊取雜湊計算 Application Key 即後續資料傳輸階段的對稱密鑰
客戶端:計算 Application Key#
客戶端使用同樣的方式計算 Application Key
客戶端:密文發送握手結束#
客戶端將握手階段的所有訊息取雜湊作為驗證訊息發送給服務端
至此客戶端和服務端之間可以通過 Application Key 進行對稱加密通訊
服務端:密文發送 Session Ticket 1#
服務端為客戶端提供 Session Ticket 用於後續快速開啟新的會話,減少會話建立階段大量的計算和網路延遲。包括:
- Ticket Lifetime 有效期
- Ticket Age Add (每個 ticket 單獨一份)
- Ticket Nonce 隨機值 (每個 ticket 單獨一份)
- Session Ticket
其中 Ticket Age Add
是由服務端生成的隨機毫秒數,客戶端在使用 Session Ticket 恢復連接時需要將 ticket_age (表示從收到 Session Ticket 到目前當前的時間差) 加上此值進行混淆。服務端收到此值後校驗客戶端的 ticket_age 和自己計算的時間差是否接近,如果超過了一定的閾值可以直接拒絕此連接。一定程度上避免了重用 Session Ticket 製造的重放攻擊。
服務端:密文發送 Session Ticket 2#
第二個 Session Ticket 由於客戶端比如瀏覽器一般會發送多個連接,且每個 Session Ticket 只能使用一次,伺服器一般會返回多個 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 證書(基礎篇)