COMIC CLASSROOM

安全基礎第 7 / 9 課

憑證與 PKI 漫畫小教室:誰替陌生公鑰背書?

從一把陌生公鑰出發,十二張漫畫帶你打開 X.509 憑證、走完信任鏈,再理解 TLS 私鑰證明、有效期限、撤銷與裝置 PKI。

13 分鐘

簽章通過以後,先問是哪一把 key

上一課先假設機器人已經信任老師的公鑰。這一課把假設拿掉:陌生公鑰跟著通知一起送來,驗證成功到底證明了誰?

跟著十二張圖依序打開 X.509、CA、trust anchor、憑證鏈、TLS 私鑰證明、到期與撤銷。先抓住每一關在回答什麼,再記縮寫。

機器人收到維修通知,附上的公鑰也能讓簽章驗證成功。可是冒牌者能自己產生一對金鑰,簽假通知,再把公鑰附上。機器人需要另外的依據,確認手上的公鑰有權代表 repair.example。這是上一課先保留、現在要處理的身分問題。

憑證把名稱與公鑰放進可驗證的聲明,PKI 則安排簽發、信任設定與生命週期。下面沿著 repair.example 的通知,打開 X.509 欄位、追蹤信任鏈,再檢查時間、用途、撤銷與 TLS 的私鑰證明。文末可逐項取消驗證條件,觀察有效簽章為何仍可能被拒絕。模型只涵蓋列出的政策條件,不是完整 PKI 驗證器。

1. 簽章通過了,這把公鑰是誰的?

憑證與 PKI 漫畫第 1 頁:簽章通過了,公鑰就是真的嗎?
圖 1:簽章能證明資料與某把公鑰相符,還沒有回答那把公鑰屬於誰。

機器人收到 repair.example 的維修通知,附件放了公鑰 K-REAL。它用這把公鑰驗證,畫面顯示 PASS。這個結果有明確範圍:收到的資料與簽章,在 K-REAL 之下符合該簽章方案的驗證規則。

麻煩是,冒牌者也能自己產生 sk-FAKE 與 K-FAKE,再用 sk-FAKE 簽一張假通知。把假通知、假簽章與 K-FAKE 綁在一起驗證,結果同樣可以 PASS。演算法沒有壞;兩邊只是各自證明了「簽章與自己的 key 相符」。

真正少掉的是身分連結:誰能替 repair.example 與 K-REAL 的關係作證?憑證負責把公鑰放進一份有身分脈絡、可被簽署的資料裡;PKI 則包含背後的角色、規則、信任設定與生命週期。它們不會讓簽章突然變強,而是補上「該用哪一把公鑰」的依據。[1][2]

2. 公鑰一多,不能每把都當面核對

憑證與 PKI 漫畫第 2 頁:公鑰太多,怎麼一一確認?
圖 2:共同信任的背書者,把大量陌生公鑰變成可驗證的身分聲明。

朋友就在旁邊時,兩人可以當面念出公鑰指紋。畫面都顯示 A7:31,至少確認了眼前這把 key 沒在傳送途中被換掉。這個方法直觀,也很適合少量、重要的關係。

可是服務一多,問題馬上失控。銀行、商店、郵件、雲端各有一把公鑰,難道每加入一個網站,就得另外安排一次可信碰面?公鑰可以公開;困難在於如何用可擴充的方式確認「名字與 key 的配對」。

PKI 把大量的一對一核對,改成可委託的信任路徑。憑證授權中心,也就是 CA,可以在完成查核後,簽署 repair.example 與 K-REAL 的綁定。驗證端不必預先認得每個陌生服務,但它仍要有自己接受的信任起點,也仍要逐項檢查憑證。[2]

3. 打開一張 X.509 憑證

憑證與 PKI 漫畫第 3 頁:認識 X.509 憑證
圖 3:X.509 把名稱、公鑰、期限、用途與簽章放進機器能處理的共同結構。

X.509 先解決格式問題。機器不用猜每家公司把名稱、key、期限放在哪裡,而是依共同結構讀取 Version、Serial、Issuer、Subject、Validity、Subject Public Key Info 與 extensions。圖中的 repair.example、K-REAL 和序號 2048 都是虛構值,欄位的工作則來自真實規範。[1][2]

CA 實際簽署的是 TBSCertificate。你可以把它想成「準備好、正要被簽的那一整包內容」:名稱、公鑰、期限、SAN、Key Usage,以及內層的 signature AlgorithmIdentifier 都在裡面。外層還會再放一個應相符的 Signature Algorithm,旁邊才是 Signature Value。

但格式正確,不等於可信。憑證完全可能語法漂亮、簽章也能算,卻已過期、名稱不符、用途不對,或一路找不到本機接受的信任錨。X.509 說明證據怎麼包;驗證政策才決定這份證據在當下能不能用。

工程師延伸:TBSCertificate 的邊界很重要

Version、序號、內層 signature AlgorithmIdentifier、Issuer、Subject、Validity、Subject Public Key Info 與 extensions 都屬於待簽內容。外層 Certificate 會再放一個應相符的 signatureAlgorithm,並以 signatureValue 承載簽章。修改 TBSCertificate 內任何一個欄位,都會破壞原有簽章。

4. 申請憑證,要過兩道不同的門

憑證與 PKI 漫畫第 4 頁:申請憑證的兩道查核
圖 4:能使用某把私鑰,與有權使用某個名稱,是兩項不同聲明。

服務先在本地產生 sk-REAL 與 K-REAL。私鑰留在受保護裝置裡,公開出去的是 K-REAL。申請時送給 CA 的 CSR,會帶著請求內容、公鑰與 CSR 簽章;CA 不需要、也不應要求拿走服務的私鑰。[4]

CSR 簽章可以讓 CA 檢查申請者是否能使用對應私鑰。可是「手上有 key」不等於「有權代表 repair.example」。名稱控制或組織授權必須另外查核,而且採用什麼證據,要看 CA 政策與憑證類型。

把兩道門分開很有用。日後若發生錯誤,我們才知道該追的是帳號被冒用、私鑰外洩,還是名稱授權程序判斷錯誤,而不是把所有問題都含糊地叫成「憑證有問題」。

工程師延伸:CSR 不是授權證明

PKCS #10 的簽章保護申請內容,並支援金鑰持有的證明;它不會自行替 requested name 建立權利。CA 還要透過獨立流程,依政策判斷名稱與屬性是否可簽發。

5. 信任不是自己簽自己

憑證與 PKI 漫畫第 5 頁:信任從哪裡開始?
圖 5:信任錨由驗證端的受控設定接受,不是因為一張憑證自己簽了自己。

沿著「誰簽的?」一直往上問,總得有停下來的地方。驗證端會先接受一組信任錨,後續再檢查憑證鏈能不能接回其中一個起點。作業系統預載、企業管理政策與受控更新,都是信任錨可能進入系統的方式。

Root 憑證常見自簽形式,卻不能把「自簽」誤讀成「自動可信」。壞人也能拿自己的 key 簽自己的憑證。真正使 Root 成為起點的,是驗證端已經透過受控程序接受那把公鑰,以及隨附的範圍與限制。[2]

信任錨是公開資料,通常要保護它不被任意替換,未必需要保密。誰能加入、刪除或更新它?更新失敗時會怎麼辦?這些看似是管理問題,實際上直接決定整條憑證鏈從哪裡開始相信。

6. 同一條鏈,簽發往下、驗證往上

憑證與 PKI 漫畫第 6 頁:一條鏈,兩個方向
圖 6:Root 往下簽發,驗證端則由 leaf 往本機接受的 trust anchor 建立路徑。

從 CA 的角度看,簽發往下走:Root CA 簽 Intermediate CA,Intermediate 再簽 repair.example。從驗證端看,方向正好相反:由服務憑證開始,逐層檢查,最後要抵達本機接受的 trust anchor。

中繼 CA 的價值,是讓 Root 私鑰少出場。Root 可以離線或極少使用,平常的簽發交給 Intermediate。某個 Intermediate 出事時,可以針對受影響的分支撤銷與替換,不必每張服務憑證都直接碰到 Root。

這是降低暴露,不是保證零風險。Intermediate 私鑰外洩,旗下憑證都要處理;Root 私鑰外洩,驗證端的信任起點也可能需要大規模更新。分層讓事件較可控制,但沒有把生命週期工作變不見。[2]

7. 憑證欄位,最後都會變成檢查

憑證與 PKI 漫畫第 7 頁:名稱、時間、用途與 CA 限制
圖 7:簽章串接正確仍不夠,名稱、時間、用途與 CA 資格都要合格。

連到 repair.example 時,驗證者要在 SAN 的 dNSName 找到相符的服務身分。拿到一張 evil.example 的有效憑證,不能因為鏈上簽章都正確,就拿來冒充 repair.example。現行 TLS 服務身分規則也不再用 Common Name 代替 SAN。[3]

時間與用途同樣要對。現在若不落在 Not Before 與 Not After 之間,就不能把憑證當成有效期內;Extended Key Usage 只允許 codeSigning 的憑證,也不能直接當作 serverAuth 使用。這些欄位要實際參與驗證,不能只當成好看的說明文字。

CA 憑證也要有資格限制。Basic Constraints 必須允許 CA 身分,Key Usage 在出現時也要允許 keyCertSign。若某把 key 根本沒有被授權簽其他憑證,它簽出來的數學結果再漂亮,也不能因此變成合格的憑證鏈。[2]

工程師延伸:Path building 與 path validation 不完全相同

Path building 是從 leaf 尋找可能通往信任錨的候選路徑;path validation 則對選定路徑套用簽章、限制、名稱與政策等規則。同一張憑證可能出現在多條候選路徑中,找到鏈不等於已通過驗證。

8. 真憑證可以影印,為什麼不會直接被冒用?

憑證與 PKI 漫畫第 8 頁:憑證可公開,私鑰仍須證明
圖 8:影印者拿得到憑證與公鑰,卻不能替這次連線產生有效的私鑰證明。

憑證本來就是要交給別人看的,攻擊者當然也能複製。影本裡仍有 repair.example、K-REAL 與 CA 的有效簽章。真正不能跟著影印機一起帶走的,應該是受保護的 sk-REAL。

以 TLS 1.3 為例,CertificateVerify 會針對目前這次 handshake 的 transcript 產生簽章。合法服務能使用 sk-REAL,影印者只有憑證與 K-REAL,做不出相符的當次證據。證明綁在這次連線內容上,也避免把概念誤講成可以到處重播的裸 challenge-response。[5]

所以兩層工作不要混在一起。憑證與驗證政策回答「這把公鑰可代表誰」;連線協定再確認眼前對方能不能使用對應私鑰。公開憑證之所以能傳送,正是因為它沒有把私鑰能力一起公開。

9. 有效期限不是安全保證書

憑證與 PKI 漫畫第 9 頁:憑證生命週期
圖 9:憑證從產生金鑰、申請、簽發走到到期或續期;續期未必換 key。

憑證有出生也有到期。金鑰產生後提出申請,CA 完成查核與簽發,服務在 Not Before 到 Not After 之間使用。超過 Not After,驗證端就不能再把它當成有效期內的憑證。

這個時間窗限制的是「何時可接受」,不是保證期間內私鑰一定安全。key 可能在第二天就被偷走,名稱控制也可能改變;日曆仍在有效期內,不會自動把這些事件修好。

續期也不一定等於換 key。服務可以沿用原本的金鑰對,只取得新憑證;也可以同時產生新 key。兩種路徑都存在,因此稽核生命週期時,不能只看憑證序號與日期,還要追蹤背後的金鑰是否輪替。

10. 私鑰提前失竊,就要談撤銷

憑證與 PKI 漫畫第 10 頁:到期前出事與撤銷
圖 10:撤銷處理到期前的提前停止,但狀態傳到每個驗證端可能有延遲。

假設 sk-REAL 在 Not After 以前被偷走。只檢查時間,憑證仍在有效期內。CA 可以透過 CRL 或 OCSP 發布提前停止接受的狀態,讓驗證端知道這張憑證已經不該繼續使用。[2][6]

狀態不一定立刻抵達每個角落。線上裝置可能取得新回應,離線產品卻還在使用舊快取;查不到時要拒絕、暫緩,還是允許,也會牽涉可用性與風險取捨。這件事必須成為明確的產品政策,不能藏在錯誤處理的預設值裡。

還要小心 OCSP 的 good。它只表示該 responder 目前沒有把這張憑證標成 revoked,不代表名稱、鏈、期限、用途與私鑰證明都已通過。到期看時間,撤銷看是否提前停止;它們是整體驗證裡兩個不同的問題。[6]

工程師延伸:狀態新鮮度也是架構選擇

CRL 的 nextUpdate、OCSP 的 producedAt/thisUpdate/nextUpdate、stapling、快取壽命、離線需求,以及 fail-open/fail-closed,都會影響事件發生後多久才真正停止接受。不能只畫一條「已撤銷」箭頭,就假設所有驗證端同時知道。

11. 把 PKI 放進裝置,兩端都要保護

憑證與 PKI 漫畫第 11 頁:裝置 PKI 與 HRoT
圖 11:裝置端保護私鑰能力,驗證端保護公開的信任起點。

製造階段可以替 MY-017 註冊身分,簽發一張綁定 MY-017 與 K-017 的裝置憑證。這張公開身分卡可以交給驗證者;對應的 sk-017 則留在 HRoT 邊界內,只允許核准操作使用,不提供直接匯出。

驗證端保護的是製造商 CA 公鑰,也就是它選定的 trust anchor。這把公鑰不必保密,但不能被攻擊者改成自己的 key。於是兩邊的保護目標很不一樣:裝置私鑰需要保密與限制使用,信任錨需要完整性與受控更新。

HUK 可能參與裝置祕密的衍生或包裝,但不要把所有 key 都畫成同一把。HUK 不會自動等於裝置身分簽署 key,更不等於製造商 CA Root。究竟是衍生、生成、wrapped 還是 provisioned,要回到產品的威脅模型與生命週期說清楚。

工程師延伸:把 HUK、裝置 key 與 CA key 分開追

HUK 常待在晶片內部;裝置身分 key 可能由它保護、衍生或完全另行配置;CA 私鑰通常位於獨立簽發系統。設計文件應逐一標示每個資產的 owner、可用操作、匯出規則、更新方式與失守後的復原路徑。

12. 不要只看一個綠勾,沿著關卡判斷

憑證與 PKI 漫畫第 12 頁:機器人的 PKI 判斷術
圖 12:假 key、影印憑證與失竊私鑰會在不同關卡暴露,處置也不同。

現在回頭看三種冒充。攻擊者自帶一把假公鑰,會卡在名稱與不可接受的鏈;影印真憑證,會卡在當次私鑰能力證明;若連真私鑰都偷到了,它在有效撤銷、到期、替換或其他生命週期措施生效前,確實可能通過。

因此,放行前要把綠勾拆開看:信任錨是否接受?憑證鏈是否有效?名稱、時間、用途與限制是否相符?撤銷狀態怎麼處理?眼前對方是否證明能使用相符私鑰?實作順序可以調整,安全主張卻不能被一個 PASS 按鈕吞掉。

最後保留一條邊界。身分驗證做完,仍不代表對方說的每句話都正確,也不代表它被授權執行所有操作。應用程式的權限、資料完整性、商業規則與人的判斷,還是要接在 PKI 後面。下一課 Secure Boot,會把這把可信公鑰放到重置起點,繼續問第一段程式碼怎麼取得執行資格。

本課帶走五件事

  • 數位簽章先回答「資料與這把公鑰是否相符」;憑證再替公鑰加入可簽署的身分脈絡。
  • X.509 定義結構,驗證政策負責鏈、名稱、時間、用途、限制與狀態。
  • Root 常是自簽,但成為 trust anchor 的原因是受控設定,不是自簽本身。
  • 憑證可以公開;周邊協定仍要取得對應私鑰的當次使用證明。
  • 到期與撤銷是不同的生命週期控制;裝置 PKI 還要同時保護私鑰能力與信任錨完整性。

參考資料

  1. ITU-T X.509 (10/2019), Public-key and attribute certificate frameworks — X.509 憑證與 certification path 的完整框架。
  2. RFC 5280, Internet X.509 Public Key Infrastructure Certificate and CRL Profile — 憑證欄位、extensions、path validation、trust anchor 與 CRL。
  3. RFC 9525, Service Identity in TLS — 現行 TLS DNS 服務身分與 SAN 比對規則。
  4. RFC 2986, PKCS #10: Certification Request Syntax Specification — CSR 的結構與申請者簽章。
  5. RFC 8446 §4.4.3, CertificateVerify — TLS 1.3 以 handshake transcript 建立當次私鑰能力證明。
  6. RFC 6960, Online Certificate Status Protocol — OCSP — good、revoked、unknown 狀態與 good 回應的解讀邊界。

一張憑證,要過哪些檢查?

從所有條件都合格開始。保留「鏈上簽章正確」,只取消 SAN 名稱符合,再逐步驗證。你會看到有效簽章無法替錯誤服務名稱放行。重置後再取消「對方能使用私鑰」,比較兩種拒絕原因。

這是六道政策檢查的教學模型,條件由你指定。沒有解析 X.509、驗證真實憑證簽章、處理撤銷或完整路徑限制;不是瀏覽器或正式 PKI 驗證器。

本次驗證條件

學習指南

安全基礎

0 / 9

查看課程大綱 → · 進度只計入已發布課程

先備知識

  • 了解私鑰簽署與公鑰驗證

我學會了什麼

  • 解釋簽章有效為何仍不能辨認陌生公鑰的主人
  • 看懂 X.509 憑證主要欄位與被簽署的邊界
  • 沿著憑證鏈走回受控設定的 trust anchor
  • 區分名稱、時間、用途、撤銷與私鑰能力檢查
  • 把裝置 PKI 接到 HRoT,且不混淆 HUK 與身分 key

本課術語

查看術語字典 →

延伸閱讀

課後小測驗

1. 簽章用隨訊息送來的公鑰驗證成功,還缺少什麼?
2. 為什麼陌生的自簽憑證不會自動可信?
3. 現行 TLS client 應從哪裡比對服務 DNS 身分?
4. OCSP 的 good 代表什麼?
5. 哪一句正確區分裝置 key 與 trust anchor?

讀到這裡,辛苦了。

把概念帶走,比把術語背走更重要。

#Certificate#PKI#X.509#憑證#Certificate Authority#Trust Anchor#憑證鏈#CSR#CRL#OCSP#HRoT#硬體安全#漫畫小教室