在基本資訊、應用資訊等考試中一定會出現的「對稱式加密」與「公開金鑰加密」。
老實說,在我還是死背應試內容的時候(也就是寫這篇文章之前),常常會猶豫「加密到底是用公開金鑰還是私密金鑰?」;但只要理解其運作原理,這種困惑幾乎就不會再出現了。
這次的目的,是從「死記硬背」往前進一步,把理解的解析度拉高一些。
本文的脈絡如下。按章節順序讀下去,就能看見各種技術之間的關聯。
「對稱式加密」就能傳遞密文!
→ 「金鑰配送問題」的兩難
→ 作為解法的「公開金鑰加密」(但處理速度較慢...)
→ 兼具兩者優點的「混合式加密」登場
→ 如果公開金鑰被掉包就完了...(中間人攻擊)
→ 作為對策基礎的「數位簽章」(可偵測竄改與冒充!)
→ 但用來驗證簽章的公開金鑰如果也被掉包就完了...
→ 由憑證機構保證公開金鑰持有者的「數位憑證」來對策!
→ 總結:把這些全部組合起來的實例「TLS」
整理一下本文會出現的技術,以及各自想達成的目標如下。
假設有兩個人想以第三者無法讀取的形式交換訊息。雙方事先共用同一把金鑰。
訊息可以用這把金鑰加密,也可以用同一把金鑰解密。
因為持有同一把金鑰就能解密,所以對第三者來說絕對是機密。
如圖所示,密文的交換非常單純。
不過,
「那麼,對稱式金鑰到底要怎麼安全地、又不被第三者知道地共享?」
「如果一開始走的就是安全通道,那就根本不需要加密;如果在不安全的通道上交換金鑰,金鑰不是也會被偷走嗎?」
大家應該會產生這些疑問。這就是所謂的「金鑰配送問題」。
而為了解決這個問題,才誕生了下一章要解說的「公開金鑰加密」。
順帶一提,金鑰配送問題的解法之一,是「Diffie-Hellman(金鑰交換)」。這是利用公開金鑰加密概念的手法,不直接傳送對稱式金鑰,而是透過公開的通訊路徑交換資訊,讓雙方各自計算出相同的秘密值。雖然這裡不詳述,但總之就是「靠著很棒的點子,能安全地建立對稱式金鑰」。
在對稱式加密中,問題在於「要如何安全地共享金鑰」。
公開金鑰加密則是藉由在加密與解密時使用不同的金鑰,來避開這個問題。
接收者會建立一組由「公開金鑰」與「私密金鑰」組成的金鑰對。
用公開金鑰加密的內容,只有配對的私密金鑰才能解密。
公開金鑰顧名思義,就算被任何人看到也沒關係。私密金鑰則由接收者自己保管,絕不外傳。
利用這個機制可以安全地交換對稱式金鑰,但這部分會在後面的「混合式加密」章節說明。
這裡我們實際試試看加密與解密。
使用 macOS 內建的 openssl 指令。
# 建立私密金鑰
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out private.pem
# 從私密金鑰取出公開金鑰
openssl pkey -in private.pem -pubout -out public.pem
# 用公開金鑰加密
echo "我的密碼是 XXXX。" > msg.txt
openssl pkeyutl -encrypt -pubin -inkey public.pem -in msg.txt -out msg.enc
# 密文無法閱讀
cat msg.enc
# 用私密金鑰解密
openssl pkeyutl -decrypt -inkey private.pem -in msg.enc
這裡雖然是一人分飾兩角,但如果把公開金鑰 public.pem 交給對方,對方再把用它加密的 msg.enc 傳回來,那麼只有持有私密金鑰 private.pem 的自己才能解密。
順帶一提,步驟中寫著「從私密金鑰取出公開金鑰」,這是因為:
由於這種單向性,所以公開金鑰即使公開也沒問題。
在大致理解對稱式加密與公開金鑰加密的運作方式之後,接下來就來比較各自的特徵。
先整理代表性的演算法。
【對稱式加密】
對稱式加密的演算法,隨著時代演進不斷經歷「被破解 → 以更強的演算法取代」的世代交替。現今主流是 AES。
演算法重點
DES / 3DES:舊美國標準的區塊密碼。DES 金鑰太短,已可被破解;3DES 則是把 DES 重複套用 3 次的延命方案。
目前已不建議使用。
RC4:曾廣泛用於 WEP 與 SSL/TLS 的串流密碼。
已發現弱點,TLS 中禁止使用。
AES:DES 的後繼者,目前的標準。
用於 TLS 與無線區域網路。
【公開金鑰加密】
公開金鑰加密的演算法,將「計算很容易,但反推非常困難」的數學問題作為安全性的根據。長期以來主流是 RSA,但近年來也廣泛使用能以較短金鑰達到同等強度的橢圓曲線密碼。
演算法重點
RSA:最具代表性的公開金鑰加密。
以大數的質因數分解困難作為安全性的根據。
名稱取自三位提出者的姓氏首字母(Rivest-Shamir-Adleman)。
橢圓曲線密碼:利用橢圓曲線上的離散對數問題困難性。
可用比 RSA 更短的金鑰長度確保同等安全性。
比較加密與解密的速度:
對稱式加密:快
公開金鑰加密:慢
【對稱式加密為什麼快】
對稱式加密的金鑰,只由送信者與接收者兩人知悉。因為金鑰本身就是秘密,所以加密機制只需要做到「讓不知道金鑰的人無法推測原始資料」即可。
若只是做混亂處理,那麼反覆進行位元交換、替換等電腦最擅長的簡單作業就夠了,因此速度很快。
【公開金鑰加密為什麼慢】
另一方面,公開金鑰加密中,用來加密的公開金鑰是人人都能知道的。即便如此仍必須安全,關鍵就在於「從公開金鑰計算出私密金鑰在實務上是不可能的」。
那是怎麼辦到的呢?靠的是「單方向容易、反方向極難」的數學關係。
例如,把兩個質數相乘很容易,但從結果反推出原本的質數(質因數分解)卻很困難。
例)61 × 53 = 3233(乘法一下就完成)
「那 3233 是哪兩個數相乘?」→ 從 2、3、5、7……等小質數開始逐一嘗試
這種位數的題目,十幾次就可能找出來,但實務上使用的是數百位數(RSA 大約 617 位數),這時連電腦也無法在現實時間內反推。
由於要做非常複雜的數學運算,合法使用者在進行加密與解密時也會變得很重,這就是公開金鑰加密較慢的原因。
【總結】
| 方式 | 處理速度 | 原因 |
|---|---|---|
| 對稱式加密 | 快 | 因為金鑰本身是秘密,只需用簡單的位元運算來混淆資料 |
| 公開金鑰加密 | 慢 | 為了避免從公開金鑰反推私密金鑰,必須對巨大數字進行重計算 |
【對稱式加密:很多】
對稱式加密中,每一組通訊雙方都需要不同的金鑰。
例如,3 個人彼此之間都要秘密通訊時,配對之間就各自需要 1 把對稱式金鑰。
因為是從 3 人中選 2 人的組合,所以是 3C2 = 3×2/2 = 3 把。
也就是說,如果有 n 人,所需數量就是 nC2,也就是 n(n−1)/2。
如果有 100 人,就需要 4,950 把,隨著人數增加,金鑰數量會暴增。
【公開金鑰加密:很少】
公開金鑰加密中,例如 3 個人彼此秘密通訊時,每個人只要各自持有一組專用金鑰對(公開金鑰與私密金鑰)即可。
A:公開金鑰 A / 私密金鑰 A
B:公開金鑰 B / 私密金鑰 B
C:公開金鑰 C / 私密金鑰 C
金鑰總數為 3 人 × 2 把(1 把公開金鑰 + 1 把私密金鑰)= 6 把(3 組)。
實際通訊時,會把公開金鑰交給對方使用。例如 B 和 C 要送給 A 時,就是這樣。
因為金鑰是綁定在「人」身上,所以不管對方有多少人,每人只需要 2 把(1 組)即可。
也就是說,n 人需要 2n 把。
如果有 100 人,只需要 200 把,和對稱式加密相比少非常多。
【總結】
| 方式 | 所需金鑰數量 | 算式 |
|---|---|---|
| 對稱式加密 | 很多 | n(n−1)/2 |
| 公開金鑰加密 | 很少 | 2n |
(補充)
在 3 人的例子中,其實公開金鑰加密所需的金鑰數量反而比較多(對稱式 3 把、公開金鑰 6 把)。兩者打平是在 5 人(都是 10 把),人數再增加後,公開金鑰加密才會明顯更少;這裡所謂的「多」與「少」是指在人數增加時的趨勢。
| 項目 | 對稱式加密 | 公開金鑰加密 |
|---|---|---|
| 加密與解密的金鑰 | 同一把金鑰 | 不同的金鑰(公開金鑰與私密金鑰) |
| 所需金鑰數量 | 多 n(n−1)/2 |
少 2n |
| 處理速度 | 快 | 慢 |
| 金鑰傳遞 | 需要安全手段(金鑰配送問題) | 公開金鑰可直接交給任何人 |
| 代表例子 | AES | RSA、橢圓曲線密碼 |
| 主要用途 | 資料本體的加密 | 金鑰共享、數位簽章(※後述) |
到這裡為止,我們已經知道對稱式加密與公開金鑰加密各有擅長與不擅長之處。
對稱式加密:處理快,但金鑰無法安全傳遞(金鑰配送問題)
公開金鑰加密:金鑰可以安全傳遞,但處理慢
把兩者的優點結合起來,同時解決金鑰配送問題與速度問題的,就是「混合式加密」。
處理流程如下。
重點在於分工。
公開金鑰加密 → 只用來安全共享對稱式金鑰
對稱式加密 → 用來加密資料本體
「這樣不就完美了嗎!」看似如此,但還有問題...
「公開金鑰本身,真的有辦法確認它是真是假嗎?」
如果攻擊者把公開金鑰掉包了,送信者就會用攻擊者的公開金鑰去加密對稱式金鑰,而攻擊者再用自己的私密金鑰解密,就能把對稱式金鑰偷走。再把內容重新加密後轉送給接收者,也不會被任何人發現。(中間人攻擊)到了這一步,內容就完全被看光了。
要防止這種事,就需要一種機制來證明「這把公開金鑰確實是接收者本人所有」,而這個機制的基礎,就是「數位簽章」。(※ 只是基礎,並不是只靠數位簽章就能完全解決)
前一章提到,如果公開金鑰被掉包,就可能遭受中間人攻擊。
簡單說,就是「收到的東西是真是假,無法辨別」這個問題。
這不只發生在公開金鑰上。加密技術是用來「隱藏內容」的,因此對於收到的資料,仍然無法得知以下事項。
能夠讓我們確認「是否為真」的,就是數位簽章。
先來看看確認資料真偽的機制。
數位簽章的做法是「用私密金鑰產生簽章,再用公開金鑰驗證」。
因為私密金鑰只有本人持有,所以只有本人能產生簽章;另一方面,公開金鑰人人都可持有,因此任何人都能驗證。也就是說,「只有本人能做出來,但任何人都能確認」。
在細說之前,先看處理流程。
實際的簽章不是針對資料本身,而是針對資料的雜湊值產生。
雜湊值是由資料計算出的固定長度短值,具有以下性質:
※ 注意:雖然不同資料產生相同雜湊值的情況確實存在,但要找出兩份不同資料卻產生相同雜湊值的組合,在實務上幾乎不可能。
由於公開金鑰加密處理較慢,若直接對大型資料簽章會很吃力。因此改為對短小的雜湊值簽章。只要資料被竄改,雜湊值也會跟著改變,所以對雜湊值簽章,就等於對整份資料簽章,效果相同。
驗證成功時,可以確認以下事項:
和加密時相反,產生金鑰對的人也不同,但這其實很合理,因為目的不同。
加密:由接收者建立金鑰對,並說「我把公開金鑰給你,你把訊息加密後傳給我」
簽章:由送信者建立金鑰對,並說「我把即將送出的資料先簽好章了,請用公開金鑰驗證它是真是假」
我們已經理解了「數位簽章」這種能識破資料竄改與冒充的方法。
「那如果把公開金鑰加上數位簽章,證明它是真的,不就能解決『公開金鑰真假問題』了嗎,這次總算完美了吧」……結果還是有問題。(到底有多少問題啊)
就算本人對自己的公開金鑰簽章,要驗證那個簽章,仍然需要本人的公開金鑰。
但我們之所以困擾,不就是因為「不知道那把公開金鑰是真是假」嗎?這根本又繞回原點。
當然,自己說「這是真的」是不算數的。
真正需要的是,讓大家都信任的第三方來簽章,證明「這把公開金鑰確實屬於這個人」。
能實現這件事的,就是「數位憑證」!!接下來進入下一章...
前一章提到的「大家都信任的第三方」,就是「憑證機構(CA)」;由憑證機構簽章並發行的憑證,就是「數位憑證」。
數位憑證主要包含以下資訊。
也就是說,這是一份由憑證機構對「這把公開金鑰的持有者是這個人」這件事所做的數位簽章。前一章學到的數位簽章,直接派上用場。
先來看公開金鑰持有者向憑證機構申請發行憑證的流程。
憑證機構會先審查提交的公開金鑰是否真的是那個人的,再用自己的私密金鑰簽章。這樣就完成了帶有「憑證機構背書」的公開金鑰。
憑證只需最初發行一次即可,之後持有者可以重複使用這張憑證(到期再更新)。
接著看收到憑證的一方,如何確認其中的公開金鑰是真是假。這個動作會在每次通訊時進行。
重點是:不是直接把公開金鑰「裸露地」傳送,而是放進帶有憑證機構背書的憑證中傳送。
另外,也要注意圖中沒有出現憑證機構。驗證時不需要每次都去向憑證機構查詢,只要使用手邊已內建的憑證機構公開金鑰即可驗證。
那如果攻擊者想掉包,會怎麼樣呢?
使用數位憑證的話,不管是哪種情況,掉包都會被識破。這樣就能防止中間人攻擊了!
「拿來驗證憑證的憑證機構公開金鑰,本身是真的嗎?」(無限質疑迴圈)
如果憑證機構的公開金鑰也是透過網路取得的,那麼它也有可能被掉包。
打破這個迴圈的,就是「根憑證機構」。
作為信任起點的最上層憑證機構(根憑證機構)之憑證,會預先內建在作業系統或瀏覽器中。因為不是經由網路傳來的,所以比較不容易被掉包。
順帶一提,根憑證是根憑證機構用自己的私密金鑰對自己的公開金鑰簽章而成。
即使是自簽章仍然可信,不是因為有簽章,而是因為作業系統或瀏覽器的開發者已經審查後將它內建進去了。
實務上,根憑證機構很少直接為網站發行憑證,中間通常會有「中繼憑證機構」介入(根憑證機構 → 中繼憑證機構 → 網站)。
中繼憑證機構的憑證(中繼憑證)會和網站自己的憑證一起送出。
像這樣,從網站憑證一路連到根憑證的整條鏈,就稱為「憑證鏈」。
驗證時會重複執行「用上一層憑證中的公開金鑰,驗證下一層憑證的簽章」。
伺服器憑證的簽章用中繼憑證的公開金鑰驗證,中繼憑證的簽章再用根憑證的公開金鑰驗證,只要一路追到手邊的根憑證即可。
中繼憑證雖然也是透過網路取得,但因為可以用內建的根憑證來驗證,所以沒有問題。
也就是說,事先需要持有的只有根憑證,之後透過逐層追蹤簽章來擴展信任。
到這裡為止所看到的憑證機構、數位憑證、根憑證等,組合起來用來保證「這把公開金鑰確實是這個人所有」的整體機制,就叫做「PKI(Public Key Infrastructure:公開金鑰基礎建設)」。
下一章要看的 HTTPS(TLS)也是建立在這個 PKI 之上。
到目前為止,我們已經從對稱式加密一路解決到數位憑證,逐一拆解了各種問題。
最後來看看,這些技術在實際上是如何組合起來使用的,也就是我們日常都在用的 HTTPS(TLS)。
順帶一提,網站所使用的數位憑證稱為「伺服器憑證(SSL/TLS 憑證)」。其機制就是前一章說明的數位憑證本身。
以下以現行主流的 TLS 1.3 為例,簡化後只保留重點來說明。
前提是,Web 伺服器事先已向憑證機構取得伺服器憑證,而瀏覽器(作業系統)中已內建根憑證。兩者都是前面數位憑證章節中看到的狀態。(以下將 Web 伺服器簡稱為「伺服器」)
TLS 通訊大致可分成「金鑰共享」、「伺服器驗證」、「資料交換」三個階段。
※ 實際流程更細,但這裡為了聚焦重點而省略。
一開始先讓瀏覽器與伺服器共享對稱式金鑰。這裡使用的是「Diffie-Hellman 金鑰交換」。
瀏覽器與伺服器會彼此交換金鑰共享用的數值,並各自使用自己的值與對方傳來的值,在本地計算出對稱式金鑰。雖然是分開計算,兩者卻能得到相同的對稱式金鑰。對稱式金鑰本身從未在網路上傳送過,因此金鑰配送問題就在這裡解決了。
從這裡開始的通訊都會用這把對稱式金鑰加密。不過,只有 Diffie-Hellman 金鑰交換,還無法知道對方到底是誰。也有可能是和攻擊者共享了金鑰,所以在傳送重要資料之前,必須先確認對方是不是本人。
前面「混合式加密」章節介紹過的「用公開金鑰加密對稱式金鑰再傳送」的方法,在 TLS 1.3 中已經廢止。因為這種方法一旦伺服器私密金鑰外洩,過去的通訊也會被解密。TLS 1.3 的 Diffie-Hellman 金鑰交換使用的是每次連線都會更換的臨時值,因此即使私密金鑰外洩,過去的通訊仍受到保護(前向保密性)。
透過兩個步驟確認對方是否真的是伺服器本人。
⑤⑥ 確認公開金鑰是真實的(數位憑證)
首先,伺服器會把自己的憑證連同中繼憑證一起送出。瀏覽器會沿著收到的憑證鏈,逐層追到中繼憑證、根憑證,並驗證簽章。同時也會檢查網域名稱是否與目前正在造訪的網站一致,以及是否在有效期限內。
如此一來,就能知道憑證中的公開金鑰確實屬於那個網站。
⑦⑧ 確認對方是否為公開金鑰的持有人本人(數位簽章)
不過,憑證本身是公開資訊,任何人都能取得。攻擊者也可以複製真正網站的憑證並傳送過來。
因此伺服器會對目前為止的交換內容,用自己的私密金鑰簽章後送出。瀏覽器若能用憑證中的公開金鑰驗證成功,就能知道對方就是持有私密金鑰的真正伺服器。
而且簽章的對象是「到目前為止的交換內容」,所以也能同時確認金鑰交換時彼此傳遞的數值沒有被掉包。中間人攻擊就是在這裡被阻擋的。
這樣一來,就確認了只有真正的伺服器才持有相同的對稱式金鑰。
最後,使用速度快的對稱式加密來交換請求與回應,也就是資料本體。
在 TLS 之中,前面各章提到的技術都各司其職。
| 階段 | 使用的技術 | 解決的問題 |
|---|---|---|
| 【1】金鑰共享 | Diffie-Hellman 金鑰交換 | 金鑰配送問題 |
| 【2】伺服器驗證(憑證) | 數位憑證(憑證鏈) | 公開金鑰被掉包 |
| 【2】伺服器驗證(簽章) | 數位簽章 | 冒充與金鑰共享值遭竄改 |
| 【3】資料交換 | 對稱式加密 | 兼顧機密性與處理速度 |
原本只是想理解對稱式加密與公開金鑰加密,結果一路追到數位簽章、數位憑證、TLS。
這次研究之後,深刻體會到加密技術並不是靠單一技術就能解決所有問題。
如果能理解技術之間的連結,以及它們被發明出來的背景,會更容易掌握。
那麼這次就到這裡。