TLS1.3 通信流程梳理,基本是從 https://tls13.xargs.org 翻譯過來的,建議看原文
客戶端:生成密鑰對#
記作 (client_priv, client_pub)
客戶端:明文發送 Client Hello Packet#
主要包含以下內容:
- 隨機數 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 Packet#
主要包含以下內容:
- 隨機數 server_random
- 選定一個 cipher suite
- 選定一個 public key
- 選定協議版本
- 返回 Key Share 包含 (server_pub)
- 壓縮方式等...
伺服端:計算 Handshake Key#
通過以下信息計算握手密鑰:
- client_pub 從 Client Hello Packet 中獲得
- server_priv 由伺服端生成
- SHA384 (ClientHello + ServerHello) 計算之前發送的消息的哈希值
後續的握手過程都通過此密鑰加密
客戶端:計算 Handshake Key#
通過以下信息計算握手密鑰:
- server_pub 從 Server Hello Packet 中獲得
- 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 證書(基礎篇)