MY 機器人在展示會場完成量測,準備把實驗報告送回 lab.example,再接收下一輪的測試指令。它的開機程式已通過 Secure Boot,眼前卻還有另一個問題:報告要經過別人管理的網路。途中如果有人假扮實驗室,機器人該拿什麼證據決定要不要交出資料?
這是虛構教學情境。主線採用 TLS 1.3 的「憑證驗證伺服器身分+暫時性 ECDHE 金鑰協議」完整握手;恢復連線、0-RTT 和雙向憑證驗證會在後段另外說明。TLS 1.3 現行規範為 2026 年 7 月發布的 RFC 9846,取代早期 RFC 8446;版本仍然叫 TLS 1.3。[1]
1. 駭客想從這條連線得到什麼?

機器人還沒按下傳送,MY 老師先圈出兩項資產:未公開的實驗報告,以及能改變設備行為的測試指令。攻擊者可能想抄走報告、把量測值改掉,或塞入一條看似來自實驗室的命令。只要有一個成功,報告即使「送到了」,任務也可能失敗。
本例給攻擊者的是路徑上的控制能力:可以觀察、轉送、插入、重送或丟棄流量;起初沒有機器人或實驗室的祕密,也不能改寫機器人的信任根。這是明確設定的威脅模型,不能單憑「大家連同一個 Wi-Fi」便認定每個人都有這些能力。TLS 要在這樣的敵意路徑上提供機密性、完整性及適用的對端身分驗證;對手仍能斷線或塞住網路,可用性需要其他設計。[1,§1、附錄 F.1]
把「安全」拆開來看,會比較容易判斷需要什麼保護。假設報告裡是一組還沒公開的量測結果,外人讀到原文,就破壞了機密性。若外人沒有讀懂報告,卻讓接收端把被改過的資料當成有效結果,受損的是完整性。這兩件事可以分別發生:藏住內容,不表示接收端一定知道內容有沒有遭到修改。
身分驗證又是另一個問題。收到一段格式正確的測試指令,最多表示它長得像這個系統的指令;任何知道格式的人,都可能照樣寫一段。機器人真正需要的證據是:這段內容來自本次連線中已通過驗證的對端。至於對端能不能要求刪除校正檔,要等知道其身分後,另查操作權限。把命令格式、對端身分、操作權限分開,才不會把「看得懂這個封包」誤認為「應該照做」。
還有一種很實際的破壞,完全不需要破解密碼:攻擊者直接丟棄資料。即使密文藏得很好、驗證做得正確,實驗室仍可能永遠收不到報告。TLS 無法強迫一條被控制的路徑替你傳送,因此產品還得決定逾時後怎麼辦、資料要不要暫存、設備可否繼續工作。這些是本例需要另行設計的可用性與安全狀態,不是再加長一把密碼金鑰就會得到的功能。[1,§1、附錄 F.1]
如果攻擊者已能直接讀取機器人的記憶體,報告甚至還沒加密就會外洩。這也是為什麼本例一開始刻意排除端點受侵:先看清楚 TLS 對付「途中有人動手」的能力,再把端點、應用和金鑰保護接回來。Secure Boot 檢查過開機程式,並不會替每條網路連線指定可信的收件人。接下來,即使機器人學會加密,它仍可能把報告親手交給假實驗室。
2. 明明有加密,報告怎麼還會外洩?

機器人提出一個直覺做法:「先找個會加密的對象,把報告鎖起來。」MY 老師畫出兩條通道:機器人連到假實驗室,假實驗室再連到真實驗室。每段都可以有加密,假實驗室卻正好是兩段的解密端,報告會在它手上變成明文。
這個反例刻意拿掉「確認對方是不是預期服務」的檢查。它說明金鑰協議與加密本身無法回答對端身分;驗證正確的 TLS 連線會把身分、握手內容與金鑰綁在一起,讓路上的攻擊者不能任意替換對端。機器人必須先知道自己要找的是 lab.example,不能拿對方臨時宣稱的名字當作驗證標準。[1,§2、附錄 F.1;2,§6.1]
把兩段連線的祕密分別叫作 K1 和 K2,問題就具體了。這只是教學代號,不是 TLS 的金鑰名稱。機器人與假實驗室使用 K1;假實驗室與真實驗室使用 K2。機器人送出的密文到達中間人後,中間人用 K1 解開,看完報告,再用 K2 加密送到真正的目的地。真實驗室回覆時,它也可以做相反方向的轉換。它不必攻破任何一段加密,因為它本來就是每一段持有相應金鑰的一方。
因此,要問的不能只有「路上有沒有明文」。在這個刻意省略驗證的反例中,兩段路上都可以是密文,但中間的解密端恰好由攻擊者控制。即使使用相同的加密演算法,對端選錯,資料依然會在錯的人手上解開。這和有人在電纜旁錄下原封不動的密文,是不同的攻擊條件。
若路上的節點只是轉送機器人與真正實驗室的握手,它沒有拿自己的材料取代雙方的 key share,就沒有因為「封包經過它」而變成金鑰協議的一端。在本例未取得端點祕密的假設下,它不會憑轉送取得 K1、K2 那種解密位置。路由器必須幫忙搬運封包,TLS 的設計正是容許不受信任的搬運者存在;需要阻止的是搬運者被誤認成通訊對象。[1,§2、附錄 F.1]
後面的身分驗證,必須和實際用來建立這條連線的材料接在一起。如果只是另外收到一份 lab.example 的證明,卻沒有檢查它是否涵蓋當下的握手,攻擊者仍可能拿自己的金鑰交換搭配別人的公開證件。這說明了為什麼 TLS 需要協定流程,不能把「有加密」和「看過憑證」兩個獨立勾選項拼在一起就結束。
3. 沒見過面的兩端,怎麼得到共同祕密?

機器人送出 ClientHello,列出可接受的版本、演算法相關選項及暫時性公開金鑰資料 key_share;實驗室用 ServerHello 選定參數並回覆自己的公開金鑰資料。這條故事採 ECDHE:兩端各保留自己的暫時性私密值,用自己的私密值與對方公開資料算出相同的共享祕密。共享祕密與最後的流量金鑰都不需要原樣寄過網路。[1,§§2、4.2、4.3.8、7.4]
「暫時性」代表這些金鑰材料為這次交換而生,使用安全亂數並在不再需要時清除。此時算得出祕密,只能表示交換可以繼續,還不能宣布對端就是實驗室。後續憑證與簽章會補上身分證據。這也接回 RSA 那一課:TLS 1.3 這條路徑不使用 RSA 傳送工作階段金鑰;RSA 仍可依所選簽章方案參與身分驗證。[1,§§1.3、4.5.2、7.4]
要理解兩邊怎麼算出相同結果,可以接回 ECC 小教室的點乘。以下只用符號說明 ECDH 的代數關係,不是可直接實作的完整 TLS 演算法。設共同的基點為 G,機器人選擇暫時性私密值 a,算出公開點 A = aG;實驗室選擇 b,算出 B = bG。A 與 B 可以放進公開交換的資料中,a 與 b 則各自留在端點。
機器人拿到 B 後,計算 aB;實驗室拿到 A 後,計算 bA。因為 aB = a(bG),而 bA = b(aG),兩邊到達同一個 abG。機器人從頭到尾不必知道 b,實驗室也不必知道 a。真實 TLS 依協商的群組,把所需結果轉成指定的共享祕密位元組;例如常見的短 Weierstrass 曲線使用共享點的 x 座標。X25519 則有其指定的輸入、輸出與檢查方式,不能把這段符號推演當成所有群組的程式碼。[1,§7.4.2]
旁觀者看得到 G、A、B,為什麼不照算?因為它沒有 a 或 b。選用合適群組與正確實作時,從公開材料恢復所需祕密被假設為計算上不可行。若私密值出自可預測的來源,攻擊者就可能直接猜它,整個困難問題被繞開了。「公開演算法」和「安全亂數產生的私密輸入」可以同時成立,保密不需要靠隱藏演算法。
但這段代數裡並沒有 lab.example。假實驗室同樣可以選自己的私密值、送自己的公開點,讓機器人與它算出相同結果。算式成功,只解決建立祕密的方法;把公鑰資料與預期服務身分連起來,還要靠後面的驗證。這正是前一節中間人反例留下的缺口。暫時性材料的清除則影響日後金鑰外洩的後果,我們會在前向保密那一節再把時間拉開來看。
工程師延伸:三種選擇不要混在一起
TLS 1.3 的 cipher suite 指定 AEAD 與 HKDF 所用雜湊,例如 TLS_AES_128_GCM_SHA256。金鑰交換群組與簽章演算法另行協商,因此看到 AES 的 suite 名稱,不能推斷憑證一定用 RSA 或 ECDSA。這裡用 ECDHE 說明共享祕密的建立;沒有涵蓋所有 PSK、混合式或其他擴充路徑。HelloRetryRequest 則是無合適 key share 等情況的分支,不畫成每次握手都必經的訊息。[1,§§4.2.1、4.2.4、4.3.3、4.3.7–4.3.8]
4. 有共同祕密,為什麼還要 HKDF?

機器人想把剛算出的祕密直接當成所有用途的鑰匙。老師替它畫出分支:握手訊息需要一組保護,報告與指令需要另一組,送出和接收也有各自方向。TLS 用 HKDF 與規定的標籤、握手摘要,逐步導出各階段的 traffic secret,再產生真正使用的金鑰與 IV。[1,§§7.1、7.3;3,§2]
ServerHello 之後,兩端已能導出握手流量金鑰,所以 EncryptedExtensions、Certificate、CertificateVerify 和 Finished 可以受到加密保護。這個順序很重要:對端身分尚在驗證,握手訊息已可加密;「看見密文」仍不足以宣布認證成功。HKDF 的分工也不會憑空增加輸入的熵,來源祕密若被猜中或上游祕密外洩,分支金鑰仍會受到影響。[1,§§2、4.5、7.1;3,§3]
traffic secret 可以先理解成「用來繼續導出特定流量保護材料的祕密」。它和真正交給 AEAD 的工作金鑰不必是同一串位元。TLS 的金鑰排程會區分握手與應用資料,也區分 client 發送和 server 發送;再從對應的 traffic secret 取得需要的 key 與 IV。這樣讀流程圖時,就不會把圖上每個帶 secret 或 key 的方塊,都當成同一把鑰匙換名字。[1,§§7.1、7.3]
HKDF 的 Extract 階段把輸入祕密整理成適合後續使用的材料,Expand 階段則把用途資訊帶入導出過程。想像同一份來源需要分配給不同工作,標籤是在說「這份輸出要用在哪裡」,但實際執行的是密碼運算,並不是在原金鑰外面貼一張便利貼。雙方知道相同祕密、使用相同規定輸入,才能各自算出對應結果,不必另外把每一把工作金鑰寄給對方。[3,§§2–3]
用途分離也有界線。不同標籤有助於避免把一個用途的導出材料誤用到另一個用途,卻不會把被偷走的上游祕密變回安全。若攻擊者取得某個能導出後續材料的來源,而且知道必要的公開輸入,它也能照相同規則往下算。這就是為什麼「產生很多不同的鑰匙」和「來源本身有足夠的保密性」要一起看。將容易猜測的輸入經過多次雜湊,不能自動補回原本缺少的熵。
另一個輸入叫作 transcript hash,也就是按規範對目前的握手紀錄計算的摘要。Hello 裡談過的內容不只是講完就忘的選單;其中指定的紀錄會參與後面的導出與驗證。若兩端所見的必要握手內容不同,後續驗證可能對不上。摘要的計算本身不需要祕密,所以單獨交換一個摘要還不足以證明身分;要把它接到祕密金鑰或私鑰簽章,才有後面要用的驗證意義。[1,§§4.1、7.1]
於是,機器人現在有能力解開接下來的握手訊息,卻還沒有足夠證據信任握手對象。這不是流程自相矛盾:解密所需的材料已備妥,認證的檢查仍在進行。本例仍扣住報告,等名稱、簽章及 Finished 等必要檢查完成,才決定是否交件。
工程師延伸:分階段,不是一把萬能金鑰
主線沒有預共享金鑰,key schedule 仍按規範用零值處理缺席的 PSK 輸入,經 Early Secret、加入 ECDHE 的 Handshake Secret,再到 Main Secret。握手流量祕密使用截至 ServerHello 的 transcript;第一代應用流量祕密使用截至 server Finished 的 transcript。握手與應用、client 與 server 都有不同的導出標籤。新版稱 Main Secret,但為相容性保留的字串標籤仍可能含 master,不可自行替換。HKDF-Extract 和 HKDF-Expand 是密碼運算,不只是把一段位元切成幾份。[1,§7.1]
5. 這張憑證,是發給我要找的服務嗎?

假實驗室拿出一張真正由可信 CA 簽發的憑證,名字卻是 other.example。機器人不能因為「簽章有效」就收下。它要驗證通往本地信任根的憑證路徑、效期與適用政策,再把預期名稱 lab.example 和憑證的服務識別名稱比對。對 DNS 名稱,檢查的是 subjectAltName 中的 dNSName;不能用看起來熟悉的 Common Name 代替。[2,§§1.2、6;6,§§4、6]
驗證標準必須先由受信任的設定或使用者原本指定的目的地建立,不能跟著攻擊者的憑證改名。本例的機器人在名稱或路徑驗證失敗時停止傳送機密報告並記錄原因;這是本例採取的應用政策。時鐘錯誤、缺中繼憑證或政策不符也可能造成驗證失敗,不能一看到失敗就說一定遭到攻擊,更不能把關閉驗證當成一般修復方式。[2,§§6.1、6.6;4]
可以把憑證想成一份可驗證來源的公鑰介紹資料,但這個比喻只處理介紹關係。憑證帶有名稱、公鑰、效期等欄位,簽發者對規定的內容做簽章。機器人不能因為憑證上印著熟悉的機構名字就相信它,而要真的檢查簽章,並沿著適用的憑證路徑,回到本地原本接受的信任根。途中每一層還有用途、限制等規則;不是把幾張憑證接起來,最後有一張自簽就算成功。[6,§§4、6]
這個「本地原本接受」很重要。假實驗室可以自行產生一組 CA 金鑰,簽一張寫著 lab.example 的憑證,再把自己的根憑證附在後面。整套簽章在數學上可能自洽,機器人卻沒有理由接受這個新根。否則對方等於同時交考卷和評分標準,根本沒有引入獨立的信任依據。憑證鏈把已有的信任往下延伸,無法憑空建立對陌生簽發者的信任。
名稱比對接著回答「這份介紹,是介紹我本來要找的服務嗎?」機器人的目的地來自受信任設定中的 lab.example;另一張對 other.example 完全有效的憑證,不能拿來滿足這個目的地。若機器人在連線後反過來說「對方自稱 other.example,那我就把預期名稱改成它」,檢查雖然永遠通過,也永遠擋不住冒充。預期名稱必須先於這次證據判斷而成立。[2,§6.1]
在實際故障排查中,也要保留這幾種檢查的差別。裝置日期錯誤,可能把尚未生效或已過期的憑證判錯;缺少中繼憑證,可能讓路徑建不起來;名稱不符,則可能是連错服務或部署設定錯誤。先看錯誤類型,再修正原因,才知道修好的是什麼。若只是把驗證整個關掉,連線恢復只能說資料送得通,不能說它已送給正確對象。
機器人現在可以接受「這把公鑰與我要找的服務有符合政策的關係」。但憑證本來就是公開資料,下載一份複本不需要知道任何私鑰。這份介紹還沒有回答眼前的連線是否真的由那把私鑰的持有者參與。
6. 憑證可以複製,怎麼證明眼前的人有私鑰?

攻擊者改拿一份 lab.example 的公開憑證複本,名稱也對了。機器人還需要 CertificateVerify:實驗室用對應的私鑰,簽署帶有角色脈絡的握手摘要;機器人用已驗證憑證裡的公鑰檢查。這把服務身分接到這一次的握手,也保護簽章涵蓋範圍內的握手內容,複製一張憑證不會自動取得這個能力。[1,§4.5.2]
圖中的「出示證件+現場證明」是比喻。真實系統不是簽任意一句「我是實驗室」,也不是替每個應用資料封包做一次公開金鑰簽章。私鑰可能由受保護的簽章服務代管,因此有效證明也不代表私鑰一定存在網頁伺服器的 RAM。若攻擊者只原封不動轉送真實雙方的握手與密文,它仍只是轉送者,沒有因此拿到可解密報告的流量金鑰。[1,§2、§4.5.2]
transcript 可以先想成兩端各自整理的握手紀錄。它不是一份由對方填好、自己照單全收的敘述;接收端會根據實際收發的握手訊息,按規範计算摘要。訊息內容和先後順序因此都重要。若機器人原本送出的 Hello 與實驗室實際收到的版本不同,雙方用來驗證的紀錄就可能不同。[1,§4.1]
為什麼不用一句永久有效的「我是實驗室」?因為這種固定的簽章沒有把當下的 Hello、key share 與這次交換連起來。攻擊者若能取得那句話的簽章,便可能反覆拿來出示。CertificateVerify 將所需的握手摘要放進帶角色脈絡的簽章輸入,使證據對應到目前這次握手,而不是對應到一份可任意挪用的自我介紹。本例伺服器這份簽章使用的握手紀錄截至 server Certificate,不含正在產生的 CertificateVerify,也還沒有後續的 Finished。[1,§4.5.2]
驗證端的工作也可以拆得很具體。它從通過政策檢查的憑證取得公鑰,從自己觀察到的訊息重建所需的 transcript hash,再用協商允許的簽章演算法檢查收到的簽章。公鑰、訊息與簽章要對得上,才有接受這份證據的理由。把別次握手的簽章貼到這一次,或把自己的 key share 塞進別人簽过的紀錄,不能沿用原來的驗證結果。
這裡的雜湊負責把握手紀錄轉成規定的摘要,簽章則讓它成為對應私鑰能力的證據。只計算雜湊的人不一定有私鑰;只拿到一張憑證的人也不一定能簽。讀到這裡,再回想假實驗室手上的憑證複本:它具備公開介紹資料,缺少的是替目前握手完成相應簽章的能力。在本例金鑰未外洩、信任設定未被改寫的前提下,複製檔案本身無法補上這一步。
服務身分與這次交換的關係建立後,雙方還要確認握手中算到的材料與所見紀錄能互相驗證。下一個 Finished 使用的是由握手祕密導出的金鑰,不再是憑證私鑰簽章。
工程師延伸:CertificateVerify 實際簽什麼?
簽章輸入由 64 個 0x20 octet、角色 context string、單一 0x00 分隔,以及截至 Certificate 的 Transcript-Hash 串接而成。server 與 client 的 context string 不同。這些欄位共同防止把其他用途的簽章搬來冒用;不能簡化成簽一個沒有脈絡的公鑰或隨機數。此處的握手摘要是規範定義的握手訊息編碼,不含 record header。[1,§§4.1、4.5.2]
7. Finished 到底確認了什麼?

CertificateVerify 已提供簽章證據,雙方仍須完成各自的 Finished。Finished 用由對應握手流量祕密導出的金鑰,對當下應涵蓋握手紀錄的 transcript hash 計算 HMAC。接收端重算比對,以確認金鑰與握手完整性。握手被改動時,可能先在簽章或 record 驗證就失敗,不必等到 Finished 才發現;任何必要驗證失敗都不能硬接下去。[1,§§4.5、4.5.3]
本例在機器人驗證 server Finished、送出 client Finished,且實驗室驗證 client Finished 後,才進入報告與指令交換。兩個 Finished 的覆蓋範圍不同:各自包含之前應納入的握手訊息,不包含正在計算的 Finished 本身。client Finished 的紀錄包含較早收到的 server Finished,所以它們不是把同一份「全對話」蓋兩次章。[1,§4.5]
HMAC 是帶有祕密金鑰的訊息驗證運算。只有公開的握手摘要,任何看到相同紀錄的人都能重算;加入從握手流量祕密導出的 finished key 後,驗證就同時依赖指定的祕密材料。接收端用相應的 key 和自己算出的 transcript hash,重算應有的驗證值,再和收到的 Finished 比較。這是「確認金鑰」的實際意思,不是把金鑰拿出來互相對答案。[1,§4.5.3]
用 server Finished 看一次:實驗室根據自己的發送方向,導出 finished key,並對這個時點應涵蓋握手前綴的 transcript hash 做 HMAC。機器人已能導出對應材料,因此可以檢查。如果雙方使用的祕密或應驗證紀錄有不一致,檢查就不能通過。這提供的證據補上了 CertificateVerify 的工作,但仍必須連同前面需要的身分與簽章檢查一起判斷,不能因 Finished 單獨通過,就略過名稱驗證。
接著換機器人送 client Finished。此時它已經收到 server Finished,所以應納入的握手前綴又向前多了一段。兩端各自按照當下的規範範圍計算,不是先把未來的訊息寫好再對整本紀錄蓋同一個章。把「不含正在計算的 Finished」想清楚,還能避免循環:若驗證值必須把自己也當作輸入,計算尚未完成,就先要求知道計算結果,規則便無法照這種方式實行。
本例沒有要求客戶端憑證,因此實驗室接受 client Finished,也不能據此辨認是登記表上的哪一台機器人。它确认了相應的握手證據,裝置身分仍需額外的認證設計。這個差別會在第九節用 mTLS 接起來;現在先讓報告經過完成驗證的通道,再看 record 如何處理被改動的資料。
MY robot lab.example
ClientHello + key_share ---------------------->
<---- ServerHello + key_share
兩端導出各方向握手金鑰
<---- {EncryptedExtensions}
<---- {Certificate}
<---- {CertificateVerify}
<---- {server Finished}
{client Finished} ---------------------------->
[實驗報告] ---------------------------------->
<---- [測試指令]
{}:握手流量金鑰保護;[]:應用流量金鑰保護
這是無 PSK、無 client certificate、無 HelloRetryRequest 的主線示意。TLS 允許伺服器在送出自己的 Finished 後、尚未收到 client Finished 前先送應用資料;此時不能據此認定客戶端身分或活性已驗證。本例採較容易閱讀的等待政策。[1,§§2、4.5.3]
8. 駭客改一個數字,接收端會怎麼做?

報告開始傳送,攻擊者把密文中的一段改掉,想讓實驗室讀到不同的量測值。TLS 1.3 的 record 層使用 AEAD,將加密與驗證整合;例如 AES-GCM 或 ChaCha20-Poly1305。接收端必須驗證成功,才能把結果當成可信的解密輸出。記錄驗證失敗會中止連線,不能把「勉強解出的內容」當成報告繼續處理。[1,§5.2]
機器人送報告和實驗室回指令使用不同方向的 traffic secret、金鑰與 IV。每個方向另有序號,用來形成 record 的 nonce,避免同一把金鑰下重複使用同一 nonce。這裡的保護層是 TLS record,不等同一個 IP 封包,也不等同一筆完整的應用交易;網路分段、重傳和應用分框是不同層次。[1,§§5.1–5.3]
加密後的位元看起來不像原文,不代表隨便改它就一定會被發現。加密和驗證在設計上各有工作,TLS 1.3 因此採用同時處理兩者的 AEAD。送件端把明文、金鑰、nonce,以及需要一起驗證的資料交給 AEAD,得到密文和驗證標記。收件端用相應的材料檢查這個標記,通過才接受解密結果。標記不需要保密;它的用途是讓不知道金鑰的人,難以替自己改過的內容造出可接受的驗證結果。[1,§5.2]
可以拿沒有祕密金鑰參與的雜湊做對照。假設攻擊者可替換報告,也可替換旁邊附上的雜湊值,它就能替新報告重算一份。接收端看到兩者相符,仍不知道誰送來。AEAD 的驗證結合了金鑰;路徑上的攻擊者即使知道完整演算法,也不能像重算普通雜湊那樣,自由替被改過的內容製造有效標記。這裡依賴的是祕密金鑰與正確的密碼構造,不是把檢查公式藏起來。
nonce 則處理「同一把金鑰會保護很多筆資料」的問題。它通常不需要保密,但在同一把金鑰下必須滿足演算法要求,不能任意重複。TLS 用每個方向自己的序號與 IV 形成 record nonce,讓接收端能按同樣的規則重建。兩端因此不只要拿到相同方向的金鑰,也要維持一致的 record 狀態;把別次連線的密文直接塞進來,不能當成新連線的一筆正常明文。[1,§5.3]
不過,record 驗證的範圍仍比「整個實驗完成」小。假設一份報告需要多筆 record 才傳完,前面收到的每筆都可以是真的,最後一部分卻因斷線沒有到。實驗室還得根據應用格式確認報告長度、結束條件和處理結果,不能只因為前面的 tag 有效,就宣稱整份報告已經交付。同樣地,TLS 不理解量測值在物理上是否合理;合法端點送出的錯誤數據,仍可能被完整而準確地傳到另一端。[1,§6.1]
工程師延伸:防竄改不等於交易只執行一次
TLS 1.3 將 64-bit record sequence number 左側補零到 IV 長度,再與該方向的 write IV 做 XOR,得到 nonce。序號不能繞回;換 traffic key 後序號重設。AEAD 的 additional data 含 record header。應用可以在另一條合法連線重試同一命令,因此交易需要自己的識別與去重政策。突然斷線時,最後一個有效 tag 也不能證明整份報告已收到。應用分框、長度檢查與 TLS close_notify 的處理仍重要。[1,§§5.2–5.3、6.1]
互動實驗真的計算 ECDH、HKDF 與 AES-GCM,但 record header 和衍生 label 都是自編教材。你可以用它比較錯誤方向、序號與密文竄改造成的 tag 失敗。這只檢查指定輸入的運算,沒有跑 TLS 握手、標準 key schedule 或憑證驗證,不能拿來替實際連線背書。
9. 實驗室知道是誰送來的嗎?

機器人已驗證實驗室,反方向的問題卻還沒自動解決:實驗室要如何知道連線的是哪一台機器人?一般伺服器憑證握手沒有替每個客戶端驗證裝置憑證;client Finished 確認的是握手金鑰與紀錄,不能直接當作某台機器人的身分證明。服務可使用應用登入機制;若選擇 mTLS,則額外請客戶端提供憑證及對應私鑰的握手證明。[1,§§4.4.2、4.5]
即使雙向身分都確認,指令仍須過權限政策。這次教學設定允許上傳報告與啟動指定測試,禁止一般操作員刪除校正檔;機器人收到「刪除校正檔」時,不能只看到 TLS 綠燈就執行。憑證或登入身分需要對應到角色、資源與允許動作。這是應用設計的推論:TLS 的認證結果是授權判斷的輸入,無法替產品定義每條命令的業務規則。[1,§1、附錄 F.1]
server 和 client 是這條連線中的角色名稱,不是可信與不可信的分界。機器人主動發起連線,所以在這裡是 client;實驗室接收連線,所以是 server。先前幾節的憑證驗證讓機器人辨認實驗室,但並沒有要求每個發起連線的 client 都拿出裝置憑證。Client Finished 所證明的,是這個 client 能完成相應的握手金鑰確認;實驗室不能只看見它,就在紀錄上填入某台已登記機器人的序號。[1,§4.5]
如果產品選擇 mTLS,實驗室會在適用的流程裡要求客戶端憑證,機器人也要提供對應私鑰能力的握手證明。接著實驗室驗證憑證、確認認證出的身分如何對應到裝置登記資料。客戶端認證的身分欄位與政策取決於這個產品,不能把前一節「比對伺服器 DNS 名称」的做法不加區分地套在所有裝置憑證上。[1,§§4.4.2、4.5]
現在假設本例把一台機器人的認證身分,對應到「可上傳報告、只能操作自己設備」的角色。即使身分驗證完全正確,它要求修改另一台設備的校正檔時,服務仍應拒絕。認證解決的是誰提出請求,授權需要把這個人或裝置,與指定資源、指定動作一起判斷。漏掉資源這一項,就可能出現「確實是合法使用者,卻操作了不屬於自己的資料」的問題。這是本例的應用政策示範,不是 TLS 替所有服務訂好的角色制度。
還可以把條件再改一次:有人偷走合法機器人的私鑰,並能用它完成認證。服務看到的密碼證據可能仍然成立,因為驗證本來就是依據憑證及私鑰能力,無法隔空辨識操作者是否為原主人。因此裝置金鑰保護、憑證撤銷、可疑操作偵測與權限縮限,都有各自的必要性。把所有檢查濃縮成畫面上的一個綠燈,反而容易忘记還有哪些判斷尚未完成。
10. 明天私鑰外洩,今天的錄包會被解開嗎?

攻擊者今天只錄下密文,明天才偷到實驗室的長期簽章私鑰。對本篇完成的 ECDHE 握手,只要暫時性與工作階段材料已安全清除、演算法與實作假設仍成立,單靠後來偷到的簽章私鑰,不能重建先前的流量金鑰。這是相對於長期金鑰的前向保密。[1,附錄 F.1]
條件一換,答案就可能不同。若取得的是運作中主機,攻擊者可能讀到明文、RAM 中的流量祕密或保留下來的 key log;若有可接受的憑證與對應簽章能力,也可能在新連線中冒充實驗室。前向保密處理的是特定的「日後長期金鑰洩漏」,不能保證端點受侵後仍能保守所有祕密,更不能救回不曾刪除的工作階段材料。[1,附錄 F.1]
理解這一節時,先把兩種私密材料放在不同抽屜。長期簽章私鑰的工作,是讓實驗室在許多次連線中證明自己的認證身分。暫時性 ECDHE 私密值則參與這一次的共享祕密計算;每次連線有自己的材料,之後再由金鑰排程導出流量祕密。這兩種工作由不同材料負責,才可能在長期簽章私鑰日後外洩時,仍保住已結束連線的內容。[1,§§4.5.2、7.1、7.4]
沿著時間順序想一次。今天,攻擊者記錄 Hello、公開 key share 和後續密文,卻沒有拿到任何私密值。連線結束後,兩端把不再需要的暫時性與工作階段材料安全清除。明天,攻擊者取得實驗室的簽章私鑰。這把 key 讓它有了簽章能力,但當初的共享祕密不是由這把簽章 key 算出來的;只把它代入之前錄下的公開 key share,並不會得到當時的 ECDHE 共享祕密。它也不能靠一份新簽章,改變昨天真正發生過的金鑰交換。
因此「有前向保密」要和「偷到了什麼」一起說。如果偷到的是保存下來的 TLS key log,裡面可能已有解密所需的工作階段材料,根本不需要回頭破解 ECDHE。如果偷到的是仍在運作的端點,明文甚至可能正放在應用程式的記憶體中。這些情境改變了外洩資產,不能拿第一個情境的結論照抄。[1,附錄 F.1]
反過來,過去連線有機會保密,也不表示明天可以繼續放心使用失竊的身分 key。若攻擊者能取得可接受的憑證並運用對應私鑰,它可能在新連線中提供有效的冒充證據。既有連線的 KeyUpdate 也不是修復任何外洩的萬靈丹:若目前的 traffic secret 已經洩漏,攻擊者可依相同導出規則跟到這條連線同一發送方向後續的 traffic secret。產品需要處理外洩根因、認證材料與重新建立安全連線,不能只按一次更新鍵就假設攻擊者已被甩掉。[1,§7.2、附錄 F.1.5、F.2]
11. 快一點重連,可以先送命令嗎?

展示網路斷線又恢復,機器人想省去重做全部驗證的成本。先前連線可建立供恢復使用的 PSK;後續被接受的 PSK 握手不必重送伺服器 Certificate 與 CertificateVerify,而是承接先前建立的安全脈絡。恢復連線不代表一定要開啟 0-RTT;搭配新的 ECDHE 與只用 PSK 的路徑,前向保密性質也不同。若這次恢復只用 PSK,攻擊者日後取得那份 PSK,配合錄下的握手資料,就能導出該次連線的流量材料;若另有安全的新 ECDHE 交換,且相關暫時性材料已清除,單靠那份 PSK 就不足以重建握手後的流量金鑰。early data 是另一回事,因為它在新交換完成前就送出了。[1,§2.2]
0-RTT 允許客戶端在取得本次 ServerHello 之前就送 early data。它能節省等待,卻沒有一般性的跨連線防重放保證,協定也不保證這些早期資料具備前向保密。若把「再執行一次測試」放進 early data,重放可能讓設備多做一次動作。這份示範政策因此讓有副作用的操作等握手完成,並另設交易識別與去重;不能只因為請求叫 GET、或聲稱冪等,就直接判定可安全重放。[1,§§2.3、8]
恢復連線利用的是雙方先前建立的安全脈絡。伺服器可在前一次連線後提供 ticket,客戶端保留恢復所需的相關材料;再次連線時提出可供辨認的 PSK 身分,並在握手中給出相應的證明。票券如何對應到伺服器保存或重建的狀態,可以有不同實作。不要把「傳回一張 ticket」想成只要影印公開字串就能登入,TLS 恢復還需要正確的 PSK 證據與後續驗證。[1,§§2.2、4.3.11、4.7.1]
省略完整憑證交換,和提前送出有副作用的資料,是兩個可以分開選的決定。機器人完全可以恢復連線,卻等新握手完成後才送出測試命令。若它選擇 0-RTT,early data 必須在看見本次伺服器的新貢獻之前就能被加密,因此不能把之後才加入的那份新 ECDHE 祕密,當成這批早期資料已經具有的保護。[1,§§2.2–2.3、7.1]
重放也不需要先看懂指令。想像攻擊者保留一份能被接受的 early-data 傳輸,再讓它在另一個可接受的連線情境出現;如果部署沒有充分限制這種重複,實驗室可能再次收到相同請求。TLS 1.3 沒有提供一般性的跨連線不重放保證,伺服器雖可用額外狀態等方式降低風險,應用仍需明白自己的假設。這和某筆密文在同一條連線內能否被直接重複接受,不是同一個問題。[1,§§2.3、8]
即使把所有操作都延後到握手完成,也還會遇到另一種重複:實驗室已執行測試,回覆卻在網路中斷時遺失。機器人只知道自己沒收到結果,無法分辨「沒有執行」還是「執行了但沒有回覆」,於是重新送出一個合法請求。新的 TLS 連線可把它安全送達,卻不知道這是同一筆工作。讓設備只執行一次,需要應用的交易識別、去重狀態與查詢結果等設計;交易識別也得和身分、請求內容及保存期限搭配,不能貼上一個編號就宣稱所有重複都消失了。
對這台有實體動作的機器人,本例選擇先完成握手,再依應用交易政策決定是否執行;連線意外中止時,先確認前一筆結果。這犧牲了一些等待時間,但比猜測馬達或量測設備究竟動過幾次更符合本例需求。0-RTT 能否用在別種請求,必須回到那個請求重做一次的實際後果,不以 HTTP 方法名稱直接下結論。
12. TLS 綠燈亮起後,還要看哪一道邊界?

回到展示桌。機器人有受信任設定指定的 lab.example,憑證路徑與名稱符合政策,對端證明能用對應私鑰參與本次握手,Finished 與 records 也通過驗證;應用再確認送件身分、報告完整性與命令權限。這些條件成立,才足以支持本例的交件與執行決定。Secure Boot 幫設備把關啟動路徑,TLS 幫它在網路上辨認對端、保護資料,兩者各處理一段信任問題。
把實驗室服務搬到代理後方,保護範圍就會出現一個新的接點。假設機器人的 TLS 連線在代理結束,代理解開報告後再轉交後端:對機器人而言,這次密碼連線的另一端就是那個終止點。它可以是受控的合法部署,不等於遭到攻擊,但代理能接觸明文,也因此需要納入存取控制、記錄政策和受侵風險。後段若另外使用 TLS,是另一條連線,有自己的對端驗證與金鑰。[1,§9.3]
機密性也不等於「別人完全看不出我在通訊」。送封包需要可路由的位址,傳輸長度與時間也可能留下線索。沒有 ECH 的基本情境裡,外人還可能從 ClientHello 的 SNI 看到服務名稱。適當部署 ECH 可縮小這一部分暴露,但只解決指定欄位的問題;若 DNS 查詢、目的 IP 或流量特徵已提供線索,不能因為某個欄位加密就宣稱目的地已匿名。這些差別會影響產品實際能對使用者承諾什麼。[1,附錄 F.3;5,§§1、10.7]
換個情境再想一次:機器人通過 mTLS,卻是帶著合法憑證的故障裝置,回報錯誤量測。TLS 能驗證傳輸身分與資料在路上未被竄改,仍不能證明量測本身正確。後端可能還需要合理範圍、跨感測器比對或裝置狀態等檢查;這些是可選的應用設計,採哪種方法要看量測目的和可取得的證據。下一篇 Key Management/Key Hierarchy,接著追問本篇用到的長期簽章金鑰、裝置金鑰與工作階段金鑰,要怎麼產生、保存、輪替及撤銷。
五個帶走的重點
- 先列出攻擊者能做什麼;加密必須和預期對端的驗證結合。
- ECDHE 建立共享祕密,HKDF 按階段和方向導出材料;它們各有工作。
- 憑證路徑與名稱、CertificateVerify、Finished 提供不同且互補的證據。
- AEAD 保護 records;裝置身分、操作權限和交易去重仍需適當機制。
- 前向保密、0-RTT、TLS 終止與端點受侵,必須各自說清楚條件。
名詞表
| 名詞 | 在這個故事裡的工作 |
|---|---|
| TLS | 建立帶有適用身分驗證與資料保護的傳輸通道。 |
| ECDHE | 用暫時性橢圓曲線金鑰資料協議共享祕密。 |
| HKDF | 萃取並依用途導出所需金鑰材料;不憑空製造熵。 |
| Transcript | 按規範累積的握手訊息紀錄。 |
| CertificateVerify | 用簽章把對應私鑰能力綁到本次握手。 |
| Finished | 使用導出金鑰的 MAC,確認握手與金鑰。 |
| AEAD | 同時提供加密與驗證的 record 保護機制。 |
| mTLS | 雙方在 TLS 中使用憑證驗證;仍需授權政策。 |
| Forward secrecy | 符合條件時,日後長期金鑰洩漏不揭露過去連線金鑰。 |
| 0-RTT | 握手尚未完成便送出的早期資料,具有不同的重放與保密邊界。 |
參考資料
1. IETF,RFC 9846:TLS 1.3,2026。
2. IETF,RFC 9525:Service Identity in TLS,2023。
3. IETF,RFC 5869:HKDF,2010。
4. IETF,RFC 9325:TLS/DTLS 使用建議,2022。
5. IETF,RFC 9849:TLS Encrypted Client Hello,2026。
6. IETF,RFC 5280:X.509 憑證與 CRL,2008。
#TLS #SecureChannel #HardwareSecurity #ECDHE #HKDF #PKI #漫畫小教室
改密文、方向或序號,record 還能通過嗎?
逐步比較兩端 ECDH shared secret、方向分離的 key 與 record nonce。一次只改密文、方向或接收端序號。再保留正確 tag,取消服務憑證或操作權限,區分 record 驗證與服務放行。
Web Crypto 真正執行 ECDH P-256、HKDF-SHA-256 與 AES-GCM,nonce 示範 IV XOR padded sequence。這是自編 record 實驗,沒有 TLS wire format、標準 key schedule、憑證解析、握手 transcript 或 Finished 驗證;不能作 TLS 實作或互通測試。憑證與授權條件由你指定。
學習指南
安全基礎
查看課程大綱 → · 進度只計入已發布課程
先備知識
- 讀過數位簽章、憑證與 PKI 會更容易銜接。
我學會了什麼
- 說明敵意路徑威脅,以及加密為何需要對端身分驗證。
- 串起 ECDHE、HKDF、憑證、Finished 與 AEAD。
- 區分傳輸保護、操作授權、重放安全與端點信任。