題目與適用情境
一個全球 API 使用 TLS 1.3。請走讀一次完整交握和一次恢復交握,解釋各階段加密了什麼、憑證如何認證伺服器、金鑰如何產生,並判斷是否應為 GET /rates 和 POST /transfers 啟用 0-RTT。
主路徑採用一組明確前提:客戶端透過 TCP 連線 HTTPS 服務;伺服器使用 X.509 憑證認證;完整交握使用暫時 ECDHE 金鑰交換;恢復連線使用伺服器在先前連線簽發的工作階段票據;API 入口可能是負載平衡器或 CDN。HTTP/3 會把 TLS 1.3 整合進 QUIC 連線建立,但本題先用 TCP 上的 TLS 記錄說明訊息順序與安全屬性。
這道題適用於後端、客戶端、基礎架構、SRE、安全和通用軟體工程職缺。完整作答需要回答三個工程問題:身分如何綁定到這次交握、不同階段的金鑰保護了什麼,以及減少一個往返為何會引入應用層必須處理的重播風險。
面試官考察重點
第一,候選人能否把金鑰交換、身分認證和資料加密分開。憑證中的公鑰通常用於驗證 CertificateVerify 對交握 transcript 的簽章,不負責加密後續大量業務資料。對稱流量金鑰來自 ECDHE、PSK 和 HKDF 金鑰計畫。
第二,能否準確說出加密邊界。初始 ClientHello 與 ServerHello 需要為協商提供資訊;雙方處理完 ServerHello 後可以得到交握流量金鑰,後續的 EncryptedExtensions、Certificate、CertificateVerify 和 Finished 受到交握金鑰保護。應用資料再使用獨立的應用流量金鑰。
第三,能否區分恢復連線與 0-RTT。工作階段恢復可以只縮短認證工作,仍按 1-RTT 完成交握;0-RTT 則允許客戶端在第一個 flight 中傳送 early data。兩者都可能使用 PSK,但只有 early data 缺少基於本次 ServerHello 的新鮮性保證。
第四,能否把協定風險落實到業務語意。RFC 對 0-RTT 明確給出較弱安全屬性:early data 不具備前向保密,且無法保證跨連線不被重播。是否允許它,不能只看 HTTP 方法名稱,還要看請求是否會產生扣款、登入、計數、發券、使用一次性權杖等副作用。
第五,能否給出可驗證的上線與除錯方法。好的回答會區分完整交握、1-RTT 恢復與 0-RTT,觀察票據、ALPN、HelloRetryRequest、early data 接受或拒絕、HTTP 425 Too Early,並確認 TLS 在邊緣終止後到來源站是否還有獨立安全通道。
回答前需要釐清的問題
- 傳輸協定是什麼? TCP 上的 HTTPS 與 QUIC/HTTP/3 都使用 TLS 1.3 的密碼學機制,但訊息承載和連線時序不同。本題主路徑按 TCP 說明。
- 是首次連線還是恢復連線? 首次連線沒有可用 PSK,需要憑證認證;恢復連線可以使用先前取得的票據,但不代表一定傳送 0-RTT。
- 伺服器是否要求客戶端憑證? 常見 Web API 只認證伺服器;mTLS 還會加入客戶端
Certificate與CertificateVerify。 - TLS 在哪裡終止? 若在 CDN 或負載平衡器終止,客戶端認證的是邊緣端點。邊緣到來源站是另一條連線,需要另外討論加密與身分。
- 業務操作的重播語意是什麼?
GET /rates是否真的唯讀?它會不會消耗一次性權杖、增加計數或觸發昂貴計算?POST /transfers即使有冪等鍵,也不能自動消除所有 early data 風險。 - 客戶端和伺服器端是否完整支援 HTTP early data? 客戶端必須能在 early data 被 TLS 層拒絕或收到
425後,使用正常交握後的連線安全重試。
30 秒回答框架
「完整 TLS 1.3 交握中,客戶端先傳送包含版本、密碼套件和 ECDHE key share 的 ClientHello;伺服器用 ServerHello 選定參數並回傳自己的 key share。雙方由 ECDHE 結果和交握 transcript 經 HKDF 衍生交握金鑰,因此 ServerHello 之後的擴充、憑證、簽章和 Finished 都被加密。客戶端驗證憑證鏈、主機名稱和 CertificateVerify,再驗證 Finished 並傳送自己的 Finished,之後雙方使用獨立應用流量金鑰。
恢復連線使用先前票據對應的 PSK,可以省去完整憑證認證;若再啟用 0-RTT,客戶端可把 early data 與 ClientHello 一起傳送。但 early data 只依賴 PSK,不具備前向保密,也可能跨連線重播。因此我只會讓明確可重試、無副作用的讀取請求進入 0-RTT;轉帳請求必須等待交握完成,並支援 425 Too Early、統一閘道策略和正常重試。」
分步深入解析
第一步:ClientHello 提供協商材料
客戶端先傳送 ClientHello。它通常包含隨機數、支援的 TLS 版本、TLS 1.3 密碼套件、簽章演算法、支援的金鑰交換群組、一個或多個 key_share,以及 SNI、ALPN 等擴充。TLS 1.3 密碼套件主要選擇對稱 AEAD 演算法和 HKDF 使用的雜湊;憑證簽章演算法與金鑰交換群組由其他擴充協商。
這條訊息在一般 TLS 1.3 中尚未由交握流量金鑰保護。SNI 也通常可見,除非客戶端與伺服器成功使用 ECH。回答「TLS 一開始就把所有欄位加密」會忽略雙方還沒有從本次交握得到共同流量金鑰。
客戶端的 key share 是暫時 ECDHE 公共值。對應私鑰必須保留在本地,不能把公共值誤稱為「共享金鑰」。雙方最後透過各自私鑰和對方公共值計算相同的 ECDHE 共享秘密。
第二步:ServerHello 完成參數選擇和新鮮金鑰交換
伺服器選擇 TLS 版本、密碼套件和可接受的 key share,並傳送 ServerHello。使用 ECDHE 時,伺服器也提供暫時公共值。ClientHello 與 ServerHello 決定本次連線的密碼學參數,雙方現在可以把 ECDHE 共享秘密送入 TLS 1.3 的 HKDF 金鑰計畫。
若客戶端沒有傳送伺服器可接受的 key share,伺服器可以先回傳 HelloRetryRequest,要求客戶端使用指定群組再傳一次 ClientHello。這會增加一個往返,而且原先嘗試的 early data 不能直接按成功路徑繼續。線上看到交握偶爾多一個 RTT 時,應檢查是否發生 HRR,不要只歸因於網路抖動。
從 ServerHello 之後,雙方已能衍生 client/server handshake traffic secrets。協定把後續交握訊息放在這些金鑰保護下,所以被動觀察者看不到憑證和大部分擴充內容,但仍可觀察記錄長度、時序和未被 ECH 隱藏的初始資訊。
第三步:伺服器參數、憑證與 transcript 簽章建立身分
伺服器隨後傳送加密的 EncryptedExtensions,其中包含對 ALPN 等 ClientHello 擴充的選擇結果;若需要客戶端憑證,還會傳送 CertificateRequest。常見單向 HTTPS 接著傳送伺服器 Certificate、CertificateVerify 和 Finished。
三個訊息承擔不同職責:
| 訊息 | 核心作用 | 常見誤解 | |---|---|---| | Certificate | 提供伺服器憑證鏈及相關擴充 | 憑證本身等於「交握已可信」 | | CertificateVerify | 使用憑證對應私鑰簽署目前交握 transcript | 憑證公鑰用於加密所有業務資料 | | Finished | 使用交握衍生金鑰驗證 transcript 完整性並提供金鑰確認 | 只驗證憑證,不驗證協商訊息 |
客戶端需要依應用程式的 PKI 政策驗證憑證鏈、有效期、主機名稱和允許的簽章演算法,再驗證 CertificateVerify 的 transcript 簽章。如此一來,伺服器控制憑證對應私鑰的事實會綁定到本次 ClientHello、ServerHello 和協商參數,攻擊者不能把另一次交握的簽章直接搬過來。
第四步:Finished 完成交握,應用金鑰與交握金鑰分離
伺服器的 Finished 是基於 transcript 和交握衍生秘密計算的校驗值。客戶端驗證成功後,確認自己看到的協商訊息沒有被竄改,且對端擁有相同的交握金鑰材料。客戶端若不做憑證認證或 Finished 驗證就接受資料,會失去 TLS 的身分和完整性保證。
客戶端隨後傳送自己的 Finished;若伺服器要求 mTLS,客戶端還會先傳送自己的憑證與 CertificateVerify。雙方為應用資料使用 application traffic secrets,不繼續重用交握金鑰。TLS 1.3 還支援透過 KeyUpdate 更新應用流量金鑰,縮小長期使用同一組流量金鑰的範圍。
前向保密來自暫時 (EC)DHE:若雙方刪除暫時私鑰和不再需要的舊流量秘密,未來伺服器憑證私鑰洩漏不應解密先前擷取的完整交握工作階段。憑證私鑰負責認證,不能把「憑證私鑰安全」誤當成前向保密的唯一來源。
第五步:工作階段票據把後續連線變成 PSK 恢復
完整交握後,伺服器可以傳送 NewSessionTicket。客戶端保存票據和關聯恢復秘密;下一次連線把票據識別作為 presharedkey 提議,並用 binder 證明自己擁有對應 PSK。伺服器接受後,可以用 PSK 認證恢復連線,通常不需再次傳送憑證鏈和 CertificateVerify。
恢復不等於放棄新鮮 ECDHE。TLS 1.3 支援 PSK-only,也支援 PSK 與 ECDHE 組合。正式系統通常更關注 PSK+DHE:它保留恢復帶來的認證與計算收益,同時讓正常 1-RTT 應用資料包含本次連線的新鮮 Diffie-Hellman 材料。PSK-only 的安全屬性不同,回答時應說明採用哪種模式。
票據也不是永久登入憑證。它有生命週期、綁定的密碼參數、伺服器金鑰輪替和叢集共享策略。多區域服務若不能一致解密或驗證票據,會退回完整交握或拒絕恢復;這屬於預期相容分支,不應為了追求恢復率而無限延長票據金鑰壽命。
第六步:0-RTT 把 early data 放進第一個 flight
若票據允許 early data,客戶端可以在恢復連線的第一個 flight 中同時傳送 ClientHello 和應用資料。early data 使用從 PSK 衍生的 client early traffic secret 加密,傳送時客戶端還沒有收到本次連線的 ServerHello。
這帶來低延遲,也帶來兩個關鍵弱點:
- early data 只由 PSK 衍生,不包含本次 ECDHE 交換,因此不具備前向保密。
- 它不依賴本次伺服器隨機數和
ServerHello,協定無法保證同一密文不會在另一條連線被重播。
伺服器可以接受或拒絕整批 TLS early data。若拒絕,客戶端必須在正常交握完成後重新傳送仍需執行的請求。這個重試能力表示應用程式原本就要面對「伺服器可能已處理、客戶端卻沒看到結果」的不確定性;0-RTT 又增加攻擊者主動製造跨連線重複的機會。
第七步:依業務副作用決定哪些請求可以提前處理
RFC 8470 在缺少額外資訊時允許客戶端對安全 HTTP 方法使用 early data,並禁止把不安全或安全性未知的方法放進去。不過方法名稱只是初步篩選,最終風險取決於資源行為。
| 請求 | 本題決策 | 原因 | |---|---|---| | GET /rates | 滿足條件後可考慮 | 必須確認唯讀、可重複、無一次性權杖、無計費或不可接受的計算副作用 | | POST /transfers | 禁止使用 0-RTT | 重播可能造成重複轉帳、重複稽核或不同時間的授權判斷 | | POST /login | 通常禁止 | 會建立工作階段、消耗挑戰或觸發風控計數 | | GET /download?token=once | 禁止只憑 GET 放行 | 一次性權杖和存取計數讓它具有不可重複副作用 |
轉帳介面即使有冪等鍵,也不應因此直接開放 0-RTT。冪等儲存必須在所有處理節點一致、在適當交易邊界內原子生效,並涵蓋稽核、通知、額度與風控等副作用;冪等鍵本身還可能被竊取請求的重播持續占用。最穩妥策略仍是讓這類操作等待交握完成。
第八步:在閘道、來源站和客戶端之間建立一致策略
HTTP 為 early data 定義 Early-Data: 1 與 425 Too Early。當閘道把可能在上一跳 early data 中收到的請求轉送給來源站時,需要保留風險訊號。來源站若不能安全處理,應回傳 425;客戶端收到後應在交握完成的連線上重試,重試本身不能繼續使用 early data。
邊緣叢集必須一致處理同類請求。若一個節點提前執行、另一個節點等待交握或拒絕,攻擊者可能利用多執行個體差異讓請求重複產生副作用。可採用的控制包括:
- 預設關閉 0-RTT,只對明確登記的唯讀資源開放。
- 限制票據壽命、early data 大小和可接受時間視窗。
- 使用共享或分區一致的 anti-replay 狀態;承認它只能降低風險,不能取代應用語意。
- 在過載時整體拒絕 early data,避免重播放大昂貴請求。
- 確保 CDN、反向 Proxy 和來源站都理解
Early-Data與425。
高品質示範回答
「我先按 TCP 上的 TLS 1.3、伺服器憑證認證和 ECDHE 完整交握回答。
客戶端傳送 ClientHello,提供支援版本、TLS 1.3 密碼套件、簽章演算法、金鑰交換群組和暫時 key share,也可能包含 SNI 與 ALPN。伺服器用 ServerHello 選擇參數並回傳自己的 key share。雙方由 ECDHE 結果和交握 transcript 經 HKDF 衍生交握流量金鑰,因此 key exchange 階段結束後,EncryptedExtensions、伺服器憑證、CertificateVerify 和 Finished 都被加密。
憑證提供伺服器身分的信任鏈;CertificateVerify 使用憑證對應私鑰簽署本次交握 transcript,把這個身分綁定到目前協商;Finished 再證明 transcript 完整,並確認雙方擁有相同交握金鑰。客戶端完成憑證鏈、主機名稱、簽章和 Finished 驗證後傳送自己的 Finished,雙方改用獨立的應用流量金鑰。憑證公鑰負責驗證身分簽章,不負責加密所有業務資料;前向保密主要來自暫時 ECDHE 和秘密清除。
後續連線可以使用 NewSessionTicket 對應的 PSK 恢復。恢復可以是 PSK+DHE 的正常 1-RTT 交握,也可以選擇 0-RTT。0-RTT 讓客戶端在 ClientHello 旁傳送 early data,但這些資料只由 PSK 衍生金鑰保護,不具備前向保密,而且可能跨連線重播。
因此我不會讓 POST /transfers 使用 0-RTT。即使介面有冪等鍵,轉帳、稽核、額度和通知也必須共同證明重複執行安全。GET /rates 只有在確認它是純讀取、可安全重試、沒有一次性權杖和不可接受副作用時才進入白名單。閘道與來源站要一致傳遞 Early-Data: 1,不安全時回傳 425 Too Early,客戶端在交握完成後重試。上線時我會分別測量完整交握、1-RTT 恢復和 0-RTT,並驗證票據接受率、HRR、early data 拒絕路徑和跨節點策略。」
常見錯誤
- 說憑證公鑰加密後續所有資料 → TLS 1.3 的業務資料使用對稱流量金鑰 → 說明憑證簽章驗證、ECDHE/PSK 和 HKDF 的不同職責。
- 說從
ClientHello開始所有內容都已加密 → 初始協商發生在交握流量金鑰建立之前 → 把加密邊界放在ServerHello後的交握訊息。 - 只驗證憑證鏈,不提 transcript → 身分還需要綁定到本次協商 → 解釋
CertificateVerify與Finished分別驗證什麼。 - 把工作階段恢復等同於 0-RTT → 恢復可以正常等待 1-RTT → 先區分 PSK 恢復,再說明 early data 是可選能力。
- 認為 0-RTT 只是少一個 RTT,沒有安全代價 → early data 不具備前向保密,也可能跨連線重播 → 把風險落實到應用副作用。
- 看到 GET 就自動開放 → GET 也可能消耗一次性權杖、記帳或觸發昂貴工作 → 依資源真實語意設定白名單。
- 認為冪等鍵自動解決轉帳重播 → 多節點一致性和周邊副作用仍可能重複 → 高風險寫入操作等待交握完成。
- 只在 CDN 開關,不檢查來源站 → TLS 終止與 HTTP 轉送跨越兩個安全邊界 → 統一邊緣、閘道、來源站和客戶端的
425處理。
追問與應對
追問一:TLS 1.3 為什麼比 TLS 1.2 更快?
典型完整 TLS 1.3 交握可以在一個網路往返內完成參數協商和伺服器認證,並移除 TLS 1.2 中部分舊演算法與多餘訊息。效能收益也來自更統一的金鑰計畫和恢復機制。不過總頁面延遲仍包含 DNS、TCP、伺服器端處理和應用資料,不能把「TLS 1.3 是 1-RTT」誤寫成「請求一定只需 1 RTT」。
追問二:伺服器憑證私鑰洩漏後,歷史流量會怎樣?
若歷史完整交握使用暫時 ECDHE,而且實作已刪除暫時私鑰與舊流量秘密,只洩漏長期憑證私鑰不應解密先前擷取的應用資料。這就是前向保密的重要價值。若洩漏的是票據加密金鑰、PSK、工作階段秘密或端點上的流量金鑰,影響範圍不同,需要結合票據壽命、日誌和金鑰輪替評估。
追問三:為什麼 anti-replay 儲存仍不能讓所有請求安全使用 0-RTT?
全球多區域系統很難在不增加延遲的情況下,對每個票據和 early data 做強一致、一次性接受。網路分割、節點狀態、票據輪替和攻擊者並行重播都會形成邊界。協定層偵測能限制成功重播的時間視窗或次數,但應用程式仍必須假設重複請求可能發生,並限制 early data 的業務範圍。
追問四:如何驗證線上實際走了完整交握、恢復還是 0-RTT?
在授權測試環境中,可使用 openssl sclient -connect api.example:443 -servername api.example -tls13 -alpn h2 檢查版本、憑證和 ALPN;再保存並重用工作階段,觀察是否恢復以及 early data 是否被接受。伺服器端應記錄不含敏感內容的交握模式和拒絕原因。封包擷取若要解密,只能在受控環境使用客戶端匯出的工作階段金鑰,並立即清理。
追問五:出現 425 Too Early 是故障嗎?
不一定。它表示伺服器不願承擔潛在重播風險,是 early data 的正常控制分支。客戶端應在交握完成後自動重試,且重試不能繼續使用 early data。若使用者頻繁感知失敗,應檢查客戶端是否實作該重試、閘道是否正確傳遞 Early-Data、不同節點策略是否一致,以及不適合的介面是否被錯誤加入 0-RTT 白名單。