圖解 | 數(shù)字簽名和數(shù)字證書的前世今生
? 前言
這是 2020 年一個平平無奇的周末,小北在家里刷著 B 站,看著喜歡的 up 主視頻。
在一旁玩手機的女朋友突然問”你知道數(shù)字證書是來干啥的不,為啥瀏覽器提示證書不可信?”
你要問這個,那我可來勁了,于是乎從加密、數(shù)字簽名一直講到了數(shù)字證書。。。終于把女朋友講睡著了,獨自寫下這篇文章。
正文
如果你能非常清晰的回答出以下問題,可以直接拉到最下面幫我點個贊~,把時間用去陪陪女朋友:
非對稱加密中公私鑰都可以加密,那么什么時候用公鑰加密,什么時候用私鑰“加密” ?
什么是數(shù)字簽名,數(shù)字簽名的作用是什么?
為什么要對數(shù)據(jù)的摘要進行簽名,而不是直接計算原始數(shù)據(jù)的數(shù)字簽名?
什么是數(shù)字證書,數(shù)字證書解決了什么問題?
這篇文章,主要圍繞數(shù)字簽名和數(shù)字證書的原理以及它們的作用展開。
爭取做到讓不具備任何密碼學基礎知識的同學都能聽懂,所以在這里需要先對齊一些加密相關的概念 。
1. 什么是加密
加密就是對明文數(shù)據(jù)按某種特殊算法進行處理,使其成為不可讀的一段代碼,通常稱為“密文“, 密文通過”密鑰“解密后還原出原來的明文,通過這樣的途徑可以達到保護數(shù)據(jù)不被非法人竊取、閱讀的目的。
定義簡單吧?那來看個題,考慮以下哪些屬于加密方法:
AES RSA MD5 BASE64 SM4
這幾種都是日常開發(fā)中常用的數(shù)據(jù)編碼技術,但是只有 AES、RSA、SM4 才能算是加密方法。
為什么呢?一個區(qū)分的簡單方法就是看編碼后的數(shù)據(jù)是否還能還原,能還原的是加密。
MD5 實際上是對數(shù)據(jù)進行有損壓縮,無論數(shù)據(jù)有多長,1KB、1Mb 還是 1G,都會生成固定 128 位的散列值,并且 MD5 理論上是不可能對編碼后的數(shù)據(jù)進行還原的,即不可逆。
MD5 因為其具有不可逆性、單向恒定性(相同的數(shù)據(jù)多次計算值不變)被廣泛應用于文件完整性驗證、口令加密以及接下來會講到的數(shù)字簽名中。
至于 BASE64 是否算做加密方法,仁者見仁。在這里不下結(jié)論,因為 BASE64 編碼不需要密鑰,且編碼后的字符串任何人都可以解碼出原串,所以一般不認為是加密方法。BASE64 常用來做轉(zhuǎn)碼,把二進制字節(jié)序列轉(zhuǎn)化為 ASCII 字符序列。
2. 加密算法的分類
加密算法按照加解密使用的密鑰是否相同,可分為:
對稱加密(Symmetric Cryptography) 非對稱加密(Asymmetric Cryptography)
1. 對稱加密
對稱加密是指加密和解密時使用同一個密鑰。

2. 非對稱加密
非對稱加密是指加密和解密使用不同的密鑰,這兩個密鑰分別叫做「公鑰」、「私鑰」。
公鑰是可以公開給所有人的,而私鑰需要自己保密的。
公鑰加密的數(shù)據(jù)只能用私鑰解密:

同理,私鑰“加密”的數(shù)據(jù)只能用公鑰“解密”:

大家注意到?jīng)],我對 私鑰“加密” 這里打了引號,為什么呢?
因為私鑰不是用來加密的,準確的說法應該是 「私鑰簽名,公鑰驗簽」。
這個問題很多同學都存在誤解,認為公私鑰都可以用于加密。
實際上不是的,至于為什么,后面講完簽名我會解釋的。
3. 故事開始
為了講這個故事,小北請來了密碼學中常用的學術情侶,Alice 和 Bob,以及竊聽者代表 Eve。
我們從 Alice、Bob 約會的故事展開,來講講其中暗藏著哪些危機,又是如何一步步化解的。
3.1 第一回合
九月,一個夜黑風高的晚上,Bob 想約 Alice 出來玩,于是給 Alice 發(fā)了一封郵件:
但我們都知道網(wǎng)絡是不可信的,并且由于消息在網(wǎng)絡中是明文傳輸?shù)模院诳涂梢暂p易的截獲、篡改甚至冒充 ?Bob。
來,我們看看黑客 Eve 是怎么干的:

瞧,Eve 輕易的拿到了郵件內(nèi)容 (竊聽),并且修改了郵件內(nèi)容 (篡改),甚至說他可以隨時冒充 Bob 給 Alice 發(fā)送郵件 (偽裝)。
如果上圖中 Eve 偽造的內(nèi)容被 Alice 接收到了,那么后果可想而知。
現(xiàn)實世界中,我們每天都在通過網(wǎng)絡進行聊天、轉(zhuǎn)賬、瀏覽不存在網(wǎng)站。
如果都是這樣明文傳輸數(shù)據(jù),顯然毫無安全感。
3.2 第二回合
既然我們不能明文傳輸,那么 Bob 和 Alice 提前商量好密鑰,使用對稱加密對郵件內(nèi)容加密不就好了~

現(xiàn)在 Bob 發(fā)送的郵件都使用和 Alice 提前商量好的密鑰加密后再傳輸。
由于沒有密鑰,Eve 就算截獲到數(shù)據(jù)也無法獲取郵件的內(nèi)容,也沒法篡改和冒充 Bob。
因為篡改后的數(shù)據(jù)必須使用密鑰再次加密 Alice 才能正確解密。
那么只要 Bob 和 Alice 能夠保證 密鑰不泄露,整個通信就是安全的。
如果密鑰泄露,被中間人截獲,那么就等同于明文通信。
所以我們不能把安全性寄托在人上面。
并且這里也存在一個問題,如果兩個人不能線下見面, 如何在網(wǎng)上安全的交換密鑰呢?
這似乎是無解的,因為交換密鑰的時候我們必須明文通信,不然對方根本看不懂。但是明文交換即意味著可能泄露。
但是別忘了我們的密碼學工具箱里還有一個好東西— 「非對稱加密」。
Bob 和 Alice 各自生成一對公私鑰,因為公鑰本來就是公開的,即可以被任何人獲取,所以可以通過網(wǎng)絡明文交換公鑰。
然后使用公鑰加密郵件內(nèi)容后發(fā)送給對方,接收者使用自己的私鑰即可解密。完美~
3.3 第三回合
來看看,在非對稱加密體系下,Bob 如何給 Alice 發(fā)消息的。
首先 Alice 需要先生成一對公私鑰,私鑰只能 Alice 自己知道,公鑰是可以讓任何人都知道的,因此可將公鑰直接發(fā)送給 Bob,就算被截獲也無所謂。

Bob 使用 Alice 的公鑰加密郵件內(nèi)容,加密后的內(nèi)容只能由 Alice 的私鑰解密,所以就算 Eve 截獲也是徒勞。
反之,如果 Alice 想給 Bob 回信,就需要用 Bob 的公鑰加密后發(fā)送。
這就解決了密鑰交換問題,也保證了郵件內(nèi)容不會泄露。也就是說現(xiàn)在可以防竊聽。
3.4 如何證明 Bob 是 Bob
不知道你注意到?jīng)]有,這里也存在另外一個問題:
Eve 也可以使用 Alice 的公鑰冒充 Bob 給 Alice 發(fā)郵件啊,因為 Alice 的公鑰本來就是公開的,任何人都可以獲得。
由于 Eve 也可以獲得 Alice 公鑰,所以沒法防止 Eve 偽造和篡改,并且對于 Alice 而言,她無法分辨出郵件到底是 Eve 發(fā)的還是 Bob。
所以這個問題的本質(zhì)就是 「Alice 如何確認郵件來自于 Bob」。
那么在生活中,我們?nèi)绾巫鲞@件事呢?
那就是讓 Bob 在紙上簽名并且按手印,因為指紋和字跡是 Bob 獨有的,其它人很難偽造。
所以我們需要在計算機中引入類似的機制:
即只有 Bob 自己能夠產(chǎn)生的獨一無二的標志,并且其它人能夠驗證這個標志確實是屬于 Bob的。
這就是我們今天要講的主題—「數(shù)字簽名」。
還記得什么是 Bob 獨有的嗎?
對,就是 Bob 自己的私鑰,Bob 用自己的私鑰對郵件內(nèi)容計算一個「簽名」,將「簽名」和郵件內(nèi)容一起發(fā)送出去,接受者 Alice 可以使用 Bob 的公鑰驗證這個簽名是否正確,這就叫「驗簽」。
如果不是 Bob 的私鑰計算的簽名,那么 Alice 用 Bob 公鑰驗簽將會出錯。

可以看到, Eve 試圖使用自己的私鑰計算簽名然后發(fā)送給 Alice, 但是 Alice 使用 Bob的公鑰進行驗簽時將會出錯!
那么 Eve 可能篡改內(nèi)容并冒充 Bob 的簽名嗎?不可能!因為內(nèi)容發(fā)生改變時,對應的簽名也需要重新計算,而簽名的生成依賴于私鑰,只要 Bob 的私鑰不泄露,簽名就不會被冒充。
啊啥?你說萬一私鑰泄露了怎么辦?那就當我沒說......
所以使用數(shù)字簽名,我們能夠鑒別消息的發(fā)送者,也就是說黑客無法偽裝發(fā)送者進行發(fā)送數(shù)據(jù),也無法篡改。
注意:
可以看出我們這里數(shù)據(jù)是明文傳輸?shù)?,存在竊聽風險。但是我們?yōu)榱岁U述數(shù)字簽名機制是如何運轉(zhuǎn)的,故意將保證信息機密性的機制省略了。
如果想要保證數(shù)據(jù)的機密性,我們常見的做法是,通信雙方通過非對稱加密安全交換對稱加密的密鑰,后續(xù)通信過程的數(shù)據(jù)都使用對稱加密保證數(shù)據(jù)機密性。
并且「簽名」的作用本身也不是用來保證數(shù)據(jù)的機密性,而是用于驗證數(shù)據(jù)來源的防止數(shù)據(jù)被篡改的,也就是確認發(fā)送者的身份。
一般而言,我們不會直接對數(shù)據(jù)本身直接計算數(shù)字簽名,為什么呢?
因為數(shù)字簽名屬于非對稱加密,非對稱加密依賴于復雜的數(shù)學運算,包括大數(shù)乘法、大數(shù)模等等,耗時比較久。
如果數(shù)據(jù)量大的時候計算數(shù)字簽名將會比較耗時,所以一般做法是先將原數(shù)據(jù)進行 Hash 運算,得到的 Hash 值就叫做「摘要」。
「摘要」就像人的指紋一樣,可以代表一個人,只要內(nèi)容發(fā)生了改變,計算出來的摘要也應該變化。
「摘要」最好是不可逆轉(zhuǎn)的,一般使用開頭提到的 MD5 作為 Hash 函數(shù),MD5 輸出的結(jié)果固定位 128 位。
為什么「摘要」最好是不可逆轉(zhuǎn)的?
因為既然 Alice 可以用 Bob 公鑰解開簽名,那么理論上其它人,比如 Eve 也可以使用 Bob 公鑰解開簽名拿到數(shù)據(jù)。
所以我們最好對數(shù)據(jù)的「摘要」進行簽名,這樣,Eve 就算解開簽名,拿到的也是「摘要」,如果摘要是不可逆轉(zhuǎn)的,也就是無法從摘要反推出原文,也就達到了保密的作用。
發(fā)送者使用私鑰對「摘要」計算數(shù)字簽名。那么接收者如何驗證呢?

接受者 Alice 收到后,取下數(shù)字簽名,同時用 Bob 的公鑰解密,得到「摘要1」,證明確實是 Bob 發(fā)的。
( 畫外音:如果使用 Bob 的公鑰驗證簽名出錯,那么簽名一定不是 Bob 的私鑰生成的)
再對郵件內(nèi)容使用相同的散列函數(shù)計算「摘要2」,與上面得到的「摘要1」進行對比,兩者一致就說明信息未被篡改。
這樣兩步分證明發(fā)送者身份和保證數(shù)據(jù)未被篡改。
3.5 這就夠了嗎?
Bob 和 Alice 現(xiàn)在可以依賴于對稱加密進行保密通信,也可以依賴于數(shù)字簽名驗證消息是否是對方發(fā)送的。
但是這一切的根基是建立在 Alice 持有的公鑰確實是 Bob的,反之亦然。
什么意思呢?
試想,Eve 如果將自己的公鑰冒充 Bob 發(fā)送給 Alice,然后 Alice 保存了下來,那以后凡是 Bob 發(fā)送的消息,反而會驗證簽名失敗,被當做冒充者。那你可能會問,為什么 Eve 可以將自己的公鑰發(fā)送給 Alice,而 Alice 毫不知情呢?
看!我們又回到了最初的起點,只不過這次被篡改的是公鑰,之前是消息本身。
因為 Bob 的公鑰是直接通過網(wǎng)絡發(fā)送給 Alice的,所以 Eve 才可以在這一步做手腳,進行篡改,將自己的公鑰冒充 Bob 發(fā)送給 Alice,也就是發(fā)送公鑰這一步?jīng)]有做到:
防篡改 防冒充
防篡改怎么和防冒充怎么實現(xiàn)的呢?
我們前面講了,就是靠數(shù)字簽名!但是數(shù)字簽名需要接受者持有發(fā)送者公鑰,才能進行驗簽。
而我們現(xiàn)在處理的是分發(fā)公鑰這一步,所以.......死鎖了。這像是先有雞還是先有蛋的問題
現(xiàn)在的問題就是「Bob 無法證明它自己是 Bob」。
這個是不是似曾相識,以前去辦事的時候經(jīng)常被要求出具「我媽是我媽」這類證明。但是我們自己說“我媽就是我媽”,人家根本不會信呀,需要一個可信第三方出具證明,比如派出所。
那么「Alice 如何才能確認 Bob 發(fā)送給自己的公鑰確實是 Bob 的,而沒有被篡改?」
在只有 Alice 和 Bob 兩人的情況下是沒法驗證的。
所以,我們這里也需要一個第三方幫 Bob證明 「Bob 的公鑰就是 Bob 的公鑰」,有點繞口令那感覺了~
3.6 數(shù)字證書
為了解決這個問題,就引入了「數(shù)字證書」,什么叫數(shù)字證書呢?
百度百科:
數(shù)字證書是指在互聯(lián)網(wǎng)通訊中標志通訊各方身份信息的一個數(shù)字認證,人們可以在網(wǎng)上用它來識別對方的身份。
因此數(shù)字證書又稱為數(shù)字標識。數(shù)字證書對網(wǎng)絡用戶在交流中的信息和數(shù)據(jù)等以加密或解密的形式保證了信息和數(shù)據(jù)的完整性和安全性。
看了這個描述,是不是感覺還是云里霧里,還是我用大白話來說吧~
只要你理解了前面的數(shù)字簽名,就能理解這里的數(shù)字證書,因為我把數(shù)字證書叫做「公鑰的數(shù)字簽名」。
為什么呢?我們引入數(shù)字證書的目的是為了保證公鑰不被篡改,即使被篡改了也能識別出來。
而防篡改的方法就是數(shù)字簽名,但是這個簽名不能我們自己做,原因說過了,因為我們的公鑰還沒分發(fā)出去,別人無法驗證。
所以只能找可信的第三方來幫我們簽名,即證書頒布機構(gòu)(CA),CA 會將:證書的頒布機構(gòu)、有效期、公鑰、持有者(subject)等信息用 CA 的私鑰進行簽名。
并且將簽名結(jié)果和這些信息放在一起,這就叫做「數(shù)字證書」。
這樣,Bob 就可以去 CA 申請一個證書,然后將自己的證書發(fā)給 Alice,那么 Alice 如何驗證這個證書確實是 Bob的呢?
當然是使用 CA 的公鑰進行驗簽。
注意:
CA 的公鑰也是需要使用證書來分發(fā)的,所以 Alice 的電腦必須安裝 CA 的證書,證書里包含了 CA 的公鑰。
收到 Bob 發(fā)過來的數(shù)字證書后,Alice 使用 CA 的公鑰進行驗證,驗證通過即證明這確實是 Bob 證書,也就可以使用證書中包含的 Bob 的公鑰,按照之前討論的流程進行通信。
那么 Eve 是否可以在中途篡改 Bob 的證書呢?
答案是不行,因為證書的信息使用 CA 的私鑰進行簽名,只要 Eve 修改了任何一個 Bit 都會導致最后簽名驗證不通過。
那 Eve 可不可以修改證書信息后自己重新計算一次證書的數(shù)字簽名呢?
也不行,因為證書的數(shù)字簽名計算依賴于 CA 的私鑰,Eve 是拿不到 CA 的私鑰的。
如果拿到了,說明什么?整個世界都是不可信的。
3.7 數(shù)字證書長啥樣
這是我電腦中的自帶的證書:

可以看到,包含了證書持有人的公鑰和證書的簽名。
另外,證書頒發(fā)機構(gòu)是有層級關系的,下級 CA 的證書是需要由上級 CA 簽名的。
換句話說一定存在根證書頒發(fā)機構(gòu),那么他們的證書是由誰簽名的呢?
答案是自簽,自己給自己認證。
這是我電腦中的一個自簽的根證書頒發(fā)機構(gòu):

為什么根證書可以自簽,誰來保證安全?
你把錢存在銀行,你會擔心嗎?我們基于對國家的信任,才信任銀行,這就是信任鏈的基礎!我們思考問題應該是分層的,如果不認可一個統(tǒng)一的基礎,一直套娃下去,那么問題就無解。
那還有個問題,如何保證根證書的可靠性?這是操作系統(tǒng)和瀏覽器預裝的,由微軟、蘋果等操作系統(tǒng)廠商來選擇根證書。
3.8 證書不可信?
那么什么情況下瀏覽器會提示 “證書不可信” 呢?
根據(jù)我們上面的分析,下面是可能的原因:
證書不是權(quán)威 CA 頒發(fā)
有些企業(yè)為了貪圖便宜使用盜版的證書,沒有經(jīng)過 CA 認證。也就是無法使用瀏覽器內(nèi)置 CA 公鑰進行驗證。
證書過期
上面說了,證書里有一項就是有效期,一般就是一年或者兩年的時間。如果證書過期,那么瀏覽器就會提示“證書不可信”
證書部署錯誤
可能是服務器證書部署出錯,比如證書與域名不匹配,因為證書里有一項是持有人信息的。
好了,饒了一大圈,Bob 終于可以安全的向 Alice 發(fā)出前往紅樹林的邀請了~
附錄
QA
現(xiàn)在我們來回答文章開頭提出的一些問題:
非對稱加密中公私鑰都可以加密,那么什么時候用公鑰加密,什么時候用私鑰“加密” ?
加密場景,那么肯定希望只有我才能解密,別人只能加密。即公鑰加密,私鑰解密。
簽名場景,既然是簽名,就希望只能我才能簽名,別人只能驗證。即私鑰簽名,公鑰驗簽
什么是數(shù)字簽名,數(shù)字簽名的作用是什么?
數(shù)字簽名就是使用私鑰對數(shù)據(jù)摘要進行簽名,并附帶和數(shù)據(jù)一起發(fā)送。可以起到防篡改、防偽裝、防否認的作用。
為什么要對數(shù)據(jù)的摘要進行簽名,而不是直接計算原始數(shù)據(jù)的數(shù)字簽名?
數(shù)據(jù)可能比較大,簽名是使用非對稱加密算法,比較耗時 防止第三方使用公鑰解開簽名后,拿到原始數(shù)據(jù) 什么是數(shù)字證書,數(shù)字證書存在解決了什么問題?
數(shù)字證書就是由 CA 機構(gòu)使用自己私鑰,對證書申請者的公鑰進行簽名認證。
數(shù)字證書解決了如何安全分發(fā)公鑰的問題,也奠定了信任鏈的基礎。
來個直擊靈魂的三連吧!
