1.楔子
現(xiàn)在網(wǎng)絡(luò)的安全性已經(jīng)變得越來越重要,各位程序員在開發(fā)過程中或多或少都會(huì)遇到公鑰、私鑰、加密、簽名等一些相關(guān)名詞。這些概念比較雜亂,容易混淆,下面就來梳理一下這部分的內(nèi)容。
2.對(duì)稱加密
在重要的信息的傳遞過程中,人們總是希望信息不會(huì)被偷看、不會(huì)被篡改,偽造等。為了達(dá)到這個(gè)要求人們一直在不斷努力著。
電報(bào)加密使用的密碼本,就是初代網(wǎng)絡(luò)安全所使用的加密方式,用法為:發(fā)信時(shí)將內(nèi)容翻譯為密文發(fā)出,收到電報(bào)的一方,使用相同的密碼本才能解密出正確的信息,否則看到的就是一堆亂碼。
這種傳統(tǒng)的加密方式就叫做對(duì)稱加密。
而對(duì)稱加密所使用的算法包括:DES、3DES、AES、DESX、Blowfish、RC4、RC5、RC6,這些算法就可以看成密鑰、或者理解為上面的密碼本。這些算法也可以稱為: "對(duì)稱加密算法"或者"傳統(tǒng)加密算法",一方使用算法進(jìn)行加密,然后另一方使用相同的算法進(jìn)行解密。
我們以《福爾摩斯探案集之跳舞的小人》一案中出現(xiàn)的小人為例

? ? ? 我們看到每一個(gè)小人都代表一個(gè)英文字符,至于小人手中的旗子則是用來分隔單詞的、也就是表示一個(gè)單詞的邊界。傳遞信息的時(shí)候,將信息用小人來代替,然后另一方看到小人的時(shí)候,再將出現(xiàn)的小人解析成信息。順便一提,劇中的女主是黑幫首領(lǐng)的女兒,犯人就是使用這些小人來向女主傳遞信息,威脅她回去。
? ? ? 這些小人和英文字符之間的對(duì)應(yīng)關(guān)系就相當(dāng)于密鑰,此時(shí)就相當(dāng)于一個(gè)對(duì)稱加密。因?yàn)闊o論是發(fā)信人還是收信人,使用的是相同的密鑰、即:小人代表的含義都是一樣的。
? ? ? ?但是對(duì)稱算法的安全性非常依賴于密鑰,泄漏密鑰就意味著任何人都可以對(duì)他們發(fā)送或接收的消息解密,所以密鑰的保密性對(duì)通信安全至關(guān)重要。所以福爾摩斯在解析出這些小人代表的含義之后,用這些小人發(fā)送信息將犯人引誘了出來。因此對(duì)于這種對(duì)稱加密來說,密鑰的安全是極其重要的。
那么對(duì)稱加密有哪些優(yōu)缺點(diǎn)呢?
優(yōu)點(diǎn):計(jì)算量小、加密速度快、加密效率高
缺點(diǎn):1.密鑰需要傳遞,難以確保密鑰安全性。2.缺乏簽名功能,即不能核對(duì)發(fā)信人身份
3.非對(duì)稱加密
? ? ? 在對(duì)稱加密中,密鑰(也就是使用的加密算法,如上文中發(fā)電報(bào)時(shí)的密碼本、小人和英文字符的對(duì)應(yīng)關(guān)系)的保密性至關(guān)重要。戰(zhàn)爭時(shí)期,電報(bào)密碼本需要通過人工渠道傳遞,這樣發(fā)報(bào)雙方才能放心的使用。
? ? ? 但如今的網(wǎng)絡(luò)通信中,顯然不可能再使用人工渠道傳遞密鑰,只有通過網(wǎng)絡(luò)來傳遞才高效快捷。這樣就有了一個(gè)矛盾:密鑰是用來保證網(wǎng)絡(luò)傳輸安全的,這個(gè)對(duì)于網(wǎng)絡(luò)安全至關(guān)重要的密鑰又需要網(wǎng)絡(luò)來傳遞給對(duì)方。
?保存密鑰最安全的方式就是不告訴任何人,不進(jìn)行傳遞,但對(duì)稱加密中,解密方必須要得到對(duì)應(yīng)的密鑰,這就又要求密鑰必須進(jìn)行傳遞,可一旦傳遞密鑰就有丟失的風(fēng)險(xiǎn)。這個(gè)"雞生蛋、蛋生雞"的問題一直困擾著人們。直至出現(xiàn)了一種算法:這套算法生成的密鑰分為兩個(gè)部分:公鑰、私鑰。
? ? ? ? 這個(gè)一分為二的密鑰對(duì)有如下特點(diǎn):
公鑰和私鑰是一個(gè)算法中兩個(gè)不同、但內(nèi)在又相關(guān)聯(lián)的參數(shù)集合,同時(shí)生成,但可以獨(dú)立使用。
公鑰加密的數(shù)據(jù)只有對(duì)應(yīng)的私鑰才可以解密(公鑰加密后公鑰也不能解密)
私鑰加密的數(shù)據(jù)也只有對(duì)應(yīng)的公鑰才可以解密。??

4.RSA 算法概述
對(duì)稱加密的模式我們很好理解,但非對(duì)稱加密算法的上述特點(diǎn)讓我們感覺很神奇,下面讓我們先來簡單看看,上述這些特點(diǎn)在數(shù)學(xué)上是怎樣實(shí)現(xiàn)的吧。在非對(duì)稱加密算法中 RSA 是使用最廣泛的一種,下面我們介紹一下 RSA。
? ?RSA 名字的由來:
? ? RSA 算法是 1977 年由共同在麻省理工學(xué)院工作工作的 羅納德·李維斯特(Ron Rivest)、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)一起提出的。RSA 就是他們?nèi)诵帐祥_頭字母拼在一起組成的。
RSA 加密利用了"單向函數(shù)"正向求解很簡單,反向求解很復(fù)雜的特性。思想如下:
對(duì)兩個(gè)質(zhì)數(shù)相乘容易,而將其合數(shù)分解很難的這個(gè)特點(diǎn)進(jìn)行的加密算法。n=p1*p2,已知 p1、p2 求 n 簡單,已知 n 求 p1、p2 困難。
(m^e)%n=c,已知 m、e、n 求 c 簡單,已知 e、n、c 求 m 很難。
? ? ? ?RSA 算法的安全性基于 RSA 問題的困難性,也就是基于大整數(shù)因子分解的困難性上。這種算法非常可靠,密鑰越長,它就越難破解。根據(jù)已經(jīng)披露的文獻(xiàn),目前被破解的最長 RSA 密鑰是 768 個(gè)二進(jìn)制位。也就是說,長度超過 768 位的密鑰,還無法破解(至少?zèng)]人公開宣布)。因此可以認(rèn)為,1024 位的 RSA 密鑰基本安全,2048 位的密鑰極其安全.
? ? ? 非對(duì)稱加密的算法比對(duì)稱加密要復(fù)雜且耗時(shí),位數(shù)越多越耗時(shí)。因此在實(shí)際使用中,一般是先用非對(duì)稱加密過程傳遞對(duì)稱加密的密鑰,之后再使用對(duì)稱加密來保證后續(xù)的通信,這樣安全性與速度就可以達(dá)到了一個(gè)平衡,HTTPS 所使用的就是這種方式,后文會(huì)詳細(xì)介紹。
5. 使用非對(duì)稱加密進(jìn)行通信
? ? ? 有了非對(duì)稱加密的公私鑰對(duì),這樣通信中僅需傳遞公鑰,甚至公鑰可以開放給所有人。需要發(fā)消息給我的人使用我的公鑰加密后發(fā)給我,只有我可以使用私鑰解密,其他人不可能獲知信息的內(nèi)容。
? ? ? ?這只是單方向的加密,雙向加密怎么辦呢?對(duì)方也創(chuàng)建一個(gè)公私鑰對(duì)就可以了。
A 根據(jù)非對(duì)稱加密算法生成自己的公私鑰對(duì)(PUBLIC_A,PRIVATE_A);
B 也根據(jù)非對(duì)稱加密算法生成自己的公私鑰對(duì)(PUBLIC_B,PRIVATE_B);
A 和 B 可以公開的交換自己的公鑰(私鑰不需要發(fā)送,各自保存好即可);
A 使用 B 的公鑰 PUBLIC_B 加密信息,發(fā)送給 B;
B 接收到消息后,使用自己保存的私鑰 PRIVATE_B 解密就可以看到消息內(nèi)容(這條消息即使被他人獲得后也是不能解密的);
同樣,B 要發(fā)消息給 A 時(shí),使用 A 的公鑰 PUBLIC_A 加密發(fā)出;
A 收到消息后使用自己的私鑰 PRIVATE_A 解密,這樣就實(shí)現(xiàn)了雙方加密的通信。
6. 簽名
? ? ? ?上面我們看到,有了公私鑰對(duì),似乎解決了加密通信的難題。但是實(shí)際使用中又出問題了,那就是 A 收到消息后如何確認(rèn)發(fā)信人是 B 而不是第三方呢?其實(shí)也很簡單,只要發(fā)消息前多進(jìn)行一次使用自己的私鑰加密的過程就可以了,這次使用自己私鑰加密信息的步驟就叫做簽名。
? ? ? ? 私鑰只有自己持有,公鑰和私鑰存在一一對(duì)應(yīng)關(guān)系,即使用公鑰只能解密出對(duì)應(yīng)私鑰加密的信息,因此就可以用私鑰的加密過程當(dāng)做驗(yàn)證身份的手段了。其實(shí)公鑰、私鑰加密數(shù)據(jù)的方法與原理都相同,只是按照用途分別命名了而已。
公鑰一般用來加密,私鑰用來簽名。
還使用上邊的例子來看一下,使用了加密和簽名之后的通信過程:
A 先使用自己的私鑰 PRIVATE_A 對(duì)消息進(jìn)行一遍加密(習(xí)慣性稱作簽名),再使用 B 的公鑰 PUBLIC_B 加密信息,然后將加密結(jié)果發(fā)送給 B。
B 接收到消息后,使用自己保存的私鑰 PRIVATE_B 解密,然后使用 A 的公鑰 PUBLIC_A 再解密一遍,如果能解密成功,就可以確保這條消息不是偽造的。
同樣,B 要發(fā)消息給 A 時(shí)先使用自己的私鑰 PRIVATE_B 對(duì)消息進(jìn)行一遍加密(習(xí)慣性稱作簽名),再使用 A 的公鑰 PUBLIC_A 加密后發(fā)出。
A 收到消息后使用自己的私鑰 PRIVATE_A 解密,然后使用 B 的公鑰 PUBLIC_B 再解密一遍,這樣就實(shí)現(xiàn)了雙方互相確認(rèn)身份的加密通信。
由于非對(duì)稱加密是復(fù)雜且耗時(shí)的,而且需要加密的內(nèi)容越長就越耗時(shí)。在實(shí)際使用中一般經(jīng)過摘要算法得到一串哈希值,然后使用私鑰對(duì)哈希值進(jìn)行加密。習(xí)慣性將這樣對(duì)摘要使用私鑰加密生成的文件叫做簽名文件。
7. 哈希值算法
生成摘要的哈希算法有如下特點(diǎn):
可以將任意長度的信息與一串固定長度的字符串建立對(duì)應(yīng)關(guān)系,即哈希值定長
哈希值算法將任意長度映射為有限長度,難免有碰撞(即,兩個(gè)不同信息算出的摘要相同)。好的哈希值算法就是能夠盡量減少碰撞的幾率
原始信息的任何一點(diǎn)修改都會(huì)導(dǎo)致計(jì)算出的哈希值的變化,從而可以用哈希值來確保消息體的完整性。
哈希值算法是單向的,即只能從原信息計(jì)算出哈希值,不能由哈希值回算得到原信息。

但是有的人可能見過網(wǎng)上有破解哈希加密的,其實(shí)它并不是反向推理,而是使用"撞庫"的方式。意思就是事先對(duì)大量不同的字符串進(jìn)行哈希加密,然后再將原來的字符串和生成的哈希值保存起來。然后根據(jù)用戶輸入的哈希值來進(jìn)行檢索,這就是"撞庫"。不過這一般都是比較簡單的哈希加密(md5),而且沒有加鹽。
常見算法有 MD5、SHA1、SHA256、SHA512 等。
大部分網(wǎng)站對(duì)用戶密碼保護(hù)也是利用哈希值單向性這個(gè)特點(diǎn)。數(shù)據(jù)庫只保存用戶密碼的哈希值,進(jìn)行登錄操作時(shí),將此次輸入的密碼再次計(jì)算哈希值與數(shù)據(jù)庫保存的哈希值對(duì)比,對(duì)比通過則認(rèn)為密碼正確。這樣即使數(shù)據(jù)庫泄露,黑客也無法獲知用戶的密碼。
這樣就演化出了目前實(shí)際使用的簽名、加密過程:
A 先使用哈希算法將要發(fā)送的消息計(jì)算出摘要,再自己的私鑰 PRIVATE_A 對(duì)摘要進(jìn)行簽名得到簽名文件,然后將原始消息和簽名文件打包到一起,使用 B 的公鑰 PUBLIC_B 加密信息,發(fā)送給 B。
B 接收到消息后,使用自己保存的私鑰 PRIVATE_B 解密,得到原始消息和一個(gè)簽名文件。使用哈希算法對(duì)原始消息計(jì)算得到一個(gè)哈希值,再使用 A 的公鑰 PUBLIC_A 對(duì)簽名文件進(jìn)行解密,得到消息的哈希值,將這兩個(gè)哈希值進(jìn)行對(duì)比,如果一致就可以認(rèn)為這條消息是 A 發(fā)送的且未經(jīng)過篡改。
8. 公鑰與證書
? ? ? ?從上邊的流程來看,似乎一切都完美了,但黑客也是絞盡腦汁的,他們還是從中找到了破綻。那就是我們對(duì) A 的身份識(shí)別是建立在相信 PUBLIC_A 的公鑰確實(shí)是 A 的,然而黑客可以輕易的發(fā)布自己的公鑰宣稱這是 A 的公鑰來欺騙我們,那我們又怎么樣區(qū)分呢?這就需要一個(gè)結(jié)構(gòu)來保證了,這個(gè)機(jī)構(gòu)把 A 提供的公鑰和 A 的相關(guān)信息放在一起組合成一份證書,這樣你從這個(gè)機(jī)構(gòu)獲取證書,就可以得到有權(quán)威機(jī)構(gòu)背書的公鑰與 A 的對(duì)應(yīng)關(guān)系。
這個(gè)機(jī)構(gòu)叫做 CA,發(fā)布的證書叫做 CA 證書。
9. 證書授權(quán)中心 CA
CA 證書授權(quán)(CertificateAuthority)中心是數(shù)字證書發(fā)行的唯一機(jī)構(gòu)。
? ? ? ?CA 中心又稱 CA 機(jī)構(gòu),即證書授權(quán)中心(Certificate Authority),或稱證書授權(quán)機(jī)構(gòu),作為電子商務(wù)交易中受信任的第三方,承擔(dān)公鑰體系中公鑰的合法性檢驗(yàn)的責(zé)任。CA 中心為每個(gè)使用公開密鑰的用戶發(fā)放一個(gè)數(shù)字證書,數(shù)字證書的作用是證明證書中列出的用戶合法擁有證書中列出的公開密鑰。CA 機(jī)構(gòu)的數(shù)字簽名使得攻擊者不能偽造和篡改證書。在 SET 交易中,CA 不僅對(duì)持卡人、商戶發(fā)放證書,還要對(duì)獲款的銀行、網(wǎng)關(guān)發(fā)放證書。它負(fù)責(zé)產(chǎn)生、分配并管理所有參與網(wǎng)上交易的個(gè)體所需的數(shù)字證書,因此是安全電子交易的核心環(huán)節(jié)。
CA 證書是逐級(jí)保證安全的,最終的根證書內(nèi)置在操作系統(tǒng)中。由操作系統(tǒng)來保證,這部分下文中會(huì)進(jìn)行介紹。
CA證書鏈如下圖:

10. HTTPS 的安全傳輸過程
? ? ? HTTPS 中的 S,就是 Secure(安全)的意思,這就是比 HTTP 多出的一份安全保證,瀏覽器驗(yàn)證了網(wǎng)站的證書后會(huì)在地址欄的左邊顯示綠色的鎖的標(biāo)志,標(biāo)志該網(wǎng)站是安全可信任的官網(wǎng)。

11. 對(duì)稱加密與非對(duì)稱加密的聯(lián)合使用
? ? ? ?由于非對(duì)稱加密是耗時(shí)的,如果在每一次 HTTPS 的數(shù)據(jù)傳輸中都使用非對(duì)稱加密是不合適的。實(shí)際上的做法是在第一次建立 HTTPS 連接時(shí)使用一次非對(duì)稱加密傳遞對(duì)稱加密的密鑰,然后就使用對(duì)稱加密來保證接下來的通信過程。
HTTPS 的通信過程如下:
瀏覽器發(fā)出 HTTPS 請(qǐng)求。
服務(wù)器返回本網(wǎng)站的證書。
瀏覽器基于內(nèi)置在操作系統(tǒng)中的CA證書鏈對(duì)網(wǎng)站證書的有效性進(jìn)行校驗(yàn)。校驗(yàn)通過后使用證書中的公鑰加密一份對(duì)稱加密的密鑰信息,發(fā)送給服務(wù)端。
服務(wù)端收到信息后使用自己的私鑰解密信息,得到瀏覽器提供的用于對(duì)稱加密的密鑰信息。之后的通信過程就使用這個(gè)對(duì)稱加密的密鑰來保護(hù)。
12.?Android 的安全啟動(dòng)過程(SecureBoot)
上一小節(jié)可以看到 HTTPS 的證書有效性還是要基于內(nèi)置在操作系統(tǒng)中的 CA 根證書的。
?那操作系統(tǒng)又是如何保證系統(tǒng)自身以及系統(tǒng)內(nèi)包含的 CA 根證書不被篡改的呢?我們以 Android 來舉例,因?yàn)橄噍^于 PC 而言,手機(jī)廠商的安全性目前做的更好。
?手機(jī)廠商建立了手機(jī)內(nèi)部處理器與手機(jī)操作系統(tǒng)的綁定關(guān)系(也就是說開啟 SecureBoot 功能的手機(jī)是不能刷非官方系統(tǒng)的),一旦刷入第三方系統(tǒng)后,手機(jī)則會(huì)不開機(jī)。這也是利用上文提到的公鑰、私鑰實(shí)現(xiàn)的,來具體看一下:
手機(jī)的處理器內(nèi)部存在一塊只能寫一次數(shù)據(jù)的 OTP 區(qū)域,出廠時(shí)會(huì)將廠商的公鑰寫入。物理上就保證了這部分不可更改。
手機(jī)操作系統(tǒng)固件會(huì)使用廠商的私鑰進(jìn)行加密。
手機(jī)處理器的第一部分啟動(dòng)程序(這部分程序也是固化在處理器內(nèi)部的不可更改)會(huì)使用 OTP 中的公鑰對(duì)操作系統(tǒng)進(jìn)行解密,解密成功才可以啟動(dòng),否則立馬變"磚"。
?????? 這個(gè)過程就叫做安全啟動(dòng),即 SecureBoot 。實(shí)際過程中為了加快校驗(yàn)速度也使用了哈希值算法,但此處僅用于說明加密啟動(dòng)的過程,忽略了部分細(xì)節(jié)。
電腦端 Intel 處理器中其實(shí)也存在類似的機(jī)制,但一般情況下 PC 都希望能夠靈活的安裝系統(tǒng),因此默認(rèn)沒有開啟 Intel 芯片中的 SecureBoot 功能。