JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

憑證、憑證機構,以及 TLS 如何建立信任

你已經會用金鑰加密、用私鑰簽署——但你怎麼知道那把金鑰是誰的?本篇順著這個揮之不去的問題,一路走到憑證、憑證機構,以及那場把陌生人的線路變成私密、可信通道的交握。

公開金鑰回答不了的那個問題

在上一篇裡,你認識了讓安全對話得以成立的兩件工具。公開金鑰密碼學給每個人一把可以隨意散發的公鑰,以及一把自己保密的私鑰,於是任何人都能加密一則只有私鑰持有者讀得到的訊息。而數位簽章讓私鑰持有者簽署某樣東西,使任何人都能驗證它確實出自他、且未被竄改。兩者都真正強大。但它們共有一道安靜而致命的縫隙。

縫隙在這裡。兩件工具都假設你早已知道手上這把公鑰是誰的。想像你連到你的銀行。銀行送你一把公鑰。你能對它加密,你能驗證以對應私鑰所做的簽章——但你怎麼知道這把金鑰屬於那家銀行,而不是屬於某個坐在線路上的攻擊者?還記得第一篇的 中間人攻擊 嗎:站在中間的人,大可遞給你他自己的公鑰,並宣稱那是銀行的。你就會把密碼直接加密送給攻擊者。公開金鑰密碼學把通道保護得很漂亮——卻保護到了錯的人身上。

憑證是一張替金鑰背書的身分證

解法借用了日常生活裡的一個點子。你的護照之所以可信,不是因為它是你自己印的,而是因為一個你們雙方都信任的政府替它背書。一張 數位憑證 正是如此:它是一把公鑰的身分證。它以機器可讀的形式說:「這把公鑰屬於 bank.example.com 這個名字」,再加上一個到期日與一些其他細節。而最關鍵的是,它帶著一個數位簽章——但不是銀行自己的簽章,因為銀行替自己背書什麼也證明不了。這個簽章,是由一個受信任的第三方做出的。

那個受信任的第三方,就是 憑證機構(CA)。CA 是一個專門查核身分、然後簽署憑證來為其背書的組織。當銀行想要一張憑證時,它向 CA 證明自己確實掌控 bank.example.com,交出它的公鑰,CA 便簽署了一份把兩者綁在一起的聲明。如今這張憑證就是一個由 CA 簽署的主張:「我,這個 CA,已經查核過這把公鑰屬於 bank.example.com。」這個簽章意味著:沒有人能在不破壞簽章的情況下竄改那個名字或那把金鑰——正是你學過的、簽章所提供的那個完整性性質。

  CERTIFICATE for bank.example.com
  ---------------------------------
  Subject  : bank.example.com
  Public key : 30 82 01 0a ... (the bank's public key)
  Valid     : 2026-01-01  to  2027-01-01
  Issuer    : Example Trust CA
  ---------------------------------
  Signature : signed by Example Trust CA's private key
              over everything above
一張憑證,剝到只剩骨幹:一個名字、它所主張的公鑰、一個有效期間、是誰背書的,以及那位背書者對整份內容所做的簽章。

你為什麼信任 CA:信任鏈與根存放區

但這只是把問題往上推了一層。要信任銀行的憑證,你就必須信任 CA 的簽章,而那意味著你需要 CA 的公鑰——你又憑什麼信任那一把?誠實的答案是:這個責任鏈總得有個盡頭,而盡頭就落在你自己的裝置裡。你的作業系統與瀏覽器,出廠時就內建了一份清單,列著幾百把它們的製造者決定要信任的 CA 公鑰。這份清單叫做 信任存放區(或根存放區),裡頭的金鑰叫做根。那些根就是錨點:你信任它們,是因為你信任打造你軟體的那一方,而那個決定,早在你開啟任何連線之前就已經做好了。

實務上,銀行的憑證通常不是由根直接簽署的。根太珍貴,不適合天天拿來用,所以由根簽署一個中介 CA,再由中介簽署銀行。這就形成一條 信任鏈:銀行憑證,由中介簽署,中介又由根簽署。你的軟體會一環一環地驗證這條鏈,用上一層憑證裡的公鑰去檢查下一個簽章,直到抵達一個它存放區裡早已信任的根。如果每一環都通過、名字與日期也都對得上,這條鏈就受信任;若有任何一環斷裂、過期,或盡頭落在一個你沒有的根,整件事就被駁回。這種分層設計就是 公開金鑰基礎設施(PKI)——由 CA、憑證與根組成的全球系統,讓素未謀面的陌生人也能建立信任。

TLS:把這一切收進一場交握

現在我們手上有了所有零件——公鑰、簽章、憑證,以及一條信任鏈——可以看著它們組裝成真正保護你連線的那個通訊協定了。傳輸層安全性(TLS,它較舊的版本叫做 SSL,這個名字沿用至今),是疊在 TCP 之上的那一層,它把一條明文可讀的位元組串流,變成私密且經過認證的串流。當你的瀏覽器顯示一把鎖、網址以 HTTPS 開頭時,那其實就是裝在 TLS 裡的 HTTP。TLS 在每條連線的開頭都會進行一場 交握:一段簡短的開場對話,在任何真正的資料流動之前,先證明身分、並協商出金鑰。

  1. 你的瀏覽器以一聲招呼開場:「我想安全地跟 bank.example.com 通話。這是我支援的加密方法,還有一個新鮮的亂數。」伺服器也以自己的招呼回覆,挑定方法,並補上它自己的一個亂數。
  2. 伺服器送出它的憑證(通常是整條鏈)。此時你的瀏覽器就做你剛學會的那件驗證:一環一環走過這條鏈、檢查每個簽章、確認它抵達一個受信任的根,並確認憑證上的名字確實是 bank.example.com 且尚未過期。
  3. 瀏覽器與伺服器接著進行一場金鑰交換——用上經驗證憑證裡的那把公鑰,加上方才那兩個亂數——協商出一個新鮮的共享秘密,線路上任何竊聽者都算不出來。它們再從中推導出一把僅供本次工作階段使用的 對稱金鑰
  4. 雙方切換到那把快速的對稱金鑰,並交換一則最後的「完成」訊息,各自涵蓋目前為止說過的一切,於是交握過程中任何竄改都會被逮到。從此刻起,每一個位元組——你的密碼、那個網頁、一切——都被工作階段金鑰加密並受完整性保護。

請留意這巧妙的分工,正是你在對稱與公開金鑰密碼學登場時看到的那一套。慢速的公開金鑰工具,在開頭做那些困難、偶一為之的差事——透過憑證證明身分、並引導出一個共享秘密——接著連線就切換到一把快速的 對稱金鑰 來處理大宗資料。你一氣呵成地同時得到了公鑰的信任與對稱金鑰的速度。這也是為什麼憑證驗證會發生在分享任何秘密之前:先檢查身分,正是為了讓你上鎖的那個盒子,被交到對的一方手裡。

HTTPS 承諾了什麼,又沒承諾什麼

交握一旦完成,那把鎖替你掙得三樣具體的東西,不多也不少。機密性:竊聽者只看得到密文,所以你的密碼與你讀的網頁,在線路上是私密的。完整性:沒有人能在傳輸途中悄悄竄改資料而不被察覺。以及伺服器的認證:你確實是在跟「持有某張憑證之私鑰的那一方」通話,而那張憑證是由一個受信任的 CA 替網址列裡的那個名字所簽發的。這三樣,乾淨地對回第一篇的 CIA 三性。這已經很多了——但它有些尖銳的邊角,常被廣泛誤解。

這裡有個最重要、必須拋棄的誤解:一張有效的憑證證明的是身分,不是誠實。它確認「這真的是位於這個名字的那個網站」——但它對「那個網站是否值得信任、是否合法、是否由正派的人經營」隻字不提。一個詐騙網站,完全可以為它自己的名字取得一張完全有效的憑證,並對你顯示一把貨真價實的鎖;那把鎖的意思是「你與這個網站之間的連線是私密的」,絕不是「這個網站很安全」。憑證認證的是網址列裡的那個名字,所以真正保護你的那個習慣,就是仔細讀那個名字。一個註冊了 bank-example-login.com 的攻擊者,能為它取得一張真憑證,看起來一樣上了鎖。

再幾點誠實的限制。TLS 隱藏你流量的內容,卻沒能完全隱藏「你有在通訊」這件事:觀察者仍看得到你連上了哪一台伺服器、以及你大約交換了多少資料。它保護傳輸中的資料,但不保護靜止中的資料——一旦你的資料抵達伺服器,TLS 的工作就結束了,之後在那裡發生的事,是伺服器的責任。而且 TLS 保護的是一條連線;它沒法修補一個被攻破的 CA、一條你點下去的釣魚連結,或是早已在你機器上的惡意程式。回想威脅那一篇:TLS 確實對被動的 竊聽、以及那種掉包成自己金鑰的經典中間人,把門關上了——那把金鑰串不到一個受信任的根,所以交握會大聲地失敗。TLS 是一個強而明確的承諾。準確知道它從哪裡開始、又在哪裡結束,正是「盲目信任那把鎖的人」與「正確讀懂那把鎖的人」之間的分野。