本文全部的內容都是根據前言中的內容進行講述。算法
人物:小藍、小紅、小黑。瀏覽器
事件:通訊安全
對稱加密就是通訊的雙方都持有同一個密鑰,加密和解密都是使用這一個密鑰進行的。舉個例子:服務器
小藍和小紅互相寫情書,可是他們不但願他們之間的信件真實內容被其餘人知道。那麼他們要怎麼保證他們的情書不被其餘人知道呢?網絡
由於信件是經過郵局進行郵寄,因此沒有辦法保證信件在運輸途中不被小黑(小黑暗戀小紅)閱讀過。可是他們只要保證他們之間的信件別人看不懂就能夠了,因此他們能夠事先約定一個寫信的規則,好比,每隔三個字取一個字或者只取每句話中間那個字等等的規則。併發
經過上面的這些規則,即便信件被小黑閱讀了,可是隻要小黑不知道這個規則,那麼小黑就不知道信件要表達的內容是什麼。從而達到了信件的真實內存不被小黑所知道。tcp
加密和解密的速度快,不會形成性能上太大的損失,尤爲是在加密大量數據的狀況下,更加明顯。工具
對稱加密最大的弊端就是商定加密規則的時候是不安全的。性能
由於小紅和小藍只能經過信件交流,因此他們的加密規則也是要經過信件進行傳輸的,可是這個信件是沒有加密的,因此這個信件上的加密規則是能夠被小黑獲取而且解讀出來的,只要小黑知道了這個加密規則,那麼後面的全部信件的內容,小黑就均可以解讀出來了。網站
爲何要限制小藍和小紅只能經過信件交流,他們不能先私底下商量好加密規則嗎?若是在真實生活中確實是能夠的,可是若是在咱們的互聯網環境下,咱們的網站是不可能跟全部用戶都私底下商量密鑰的,咱們只能經過一個請求生成一個對稱密鑰發送給用戶,後續的通訊雙方都使用這個對稱密鑰對內容進行加密和解密,可是一開始生成併發送密鑰的這個請求是明文的,只要是明文的,那麼就是有風險的。
非對稱加密存在兩個密鑰,一個稱爲私鑰,一個稱爲公鑰。既可使用公鑰加密,也可使用私鑰加密。可是使用公鑰加密,那麼就只有私鑰才能解密;使用私有加密,就只能使用公鑰解密。
繼續使用上面的場景,小紅和小藍髮現他們的信件老是有被拆開的痕跡,他們意識到他們的信件被第三者閱讀過,他們固然不樂意,本身的小祕密怎麼能夠被第三者褻瀆。小藍髮現將密鑰明文傳輸很是不安全,因此它決定將一個保險箱先傳遞給小紅,而後小紅將寫好的信件放進保險箱中,而後上鎖,而打開保險箱的鑰匙只有小藍纔有,而且這個鑰匙從未被其餘人看到過。
其中,保險箱就是公鑰,鑰匙就是私鑰。通過保險箱(公鑰)加密的內容,只有鑰匙(私鑰)才能解開。
公鑰是任何人均可以獲取的。
通過公鑰加密的內容,只有私鑰才能夠解開。
必須保證私鑰不能泄露,不然將無加密可言。這個弊端仍是能夠接受的。
非對稱加密相對於對稱加密而言性能損耗較大,因此通常狀況下都會結合非對稱加密和對稱加密一塊兒使用,https的作法就是如此。
可是非對稱加密還有一個最大的漏洞:中間人攻擊,如圖所示,
咱們從中能夠看到,最關鍵的部分就是小黑攔截了小藍的保險箱,並將它替換爲了本身的保險箱,可是小藍和小紅對此是一無所知的,由於小紅不知道小藍髮送的保險箱是怎麼樣的,她只能肯定她能收到一個保險箱。而小藍也不知道本身發送的保險箱被攔截了,由於他收到的回信中確實是他本身的保險箱,也能使用本身的鑰匙打開。
衆所周知,http在網絡中傳輸的報文都是明文的,也就至關於咱們是在網絡的世界中裸奔。咱們只要經過嗅探器Wireshark、tcpdump、dsniff等工具對網絡中的信息進行獲取,就能夠獲取到網絡上其餘人發送的信息。
https是由http協議 + tls / ssl 協議組合而成的。
https = http + tls / ssl
這是咱們使用http協議時能夠接觸獲得的網絡協議層:
這是咱們使用https協議時能夠接觸獲得的網絡協議層:
咱們能夠看到https就是在TCP與HTTP之間加入了一個TLS/SSL層。
如下是訪問掘金主頁時,發生的網絡請求,我經過Wireshark抓包來解析Https的握手過程。我會直接省略tcp的三次握手過程,只關注tls/ssl的握手過程。
IP協議層:左邊紅色方框的是個人內網地址,它會在訪問外網的時候經過路由器的NAT協議轉換爲外網的地址,右邊紅色方框就是掘金的外網地址。
TCP協議層:左邊紅色方框的是我發送這條請求時使用的端口(也叫源端口),咱們接下來要使用這個端口(最好加上序號)來尋找服務器回覆給個人信息。右邊的紅色方框就是我要訪問的目的端口,這裏能夠看出Https使用的端口是443,而https的默認端口就是443,http協議的默認端口是80。
咱們大體能夠理解爲,IP是爲了找到一臺主機,而TCP是爲了找到主機上的一個進程。
TLS協議層:比較重要的是藍色方框中的內容。
服務端接受到客戶端發送的Client Hello後,會當即發送一個該類型的信息。
咱們經過紅色方框中的地址和端口號,能夠肯定該信息會回覆上面那條Client Hello的。
咱們依然看到藍色方框中的內容:
此時客戶端和服務端就已經協商好了版本號,密碼套件,而且客戶端和服務端都擁有了兩個隨機數。
緊接着Server Hello信息,服務端會馬上發送一個Server Certificate信息,該信息包含了一個很重要的東西——CA證書,也就是咱們平時說的數字證書。
能夠看到紅色方框中的就是CA證書。
該證書一般有兩個目的:
該消息是有條件才發送的,還記得剛剛在Server Hello中說的,選擇不一樣的密碼套件會有不一樣的動做產生,該信息的發送就是屬於不一樣的動做。
它發送的條件是,若是證書包含的信息不足以進行密鑰交換,那麼必須發送該信息。一般協商的加密套件屬於下面的類型,就會發送:
咱們能夠看到客戶端和服務端協商出來的密碼套件是屬於ECDHE_RSA類型的。因此這裏咱們能夠看到該信息的發送。而且該信息是緊跟着Server Certificate信息的。
客戶端每次鏈接服務器的時候,服務器都會發送動態DH信息(DH參數和DH公鑰,DH公鑰並非證書上的那個公鑰),這些信息不存在證書中,須要經過Server Key Exchange信息來進行信息傳遞,而且傳遞的DH信息須要使用服務器的私鑰進行簽名。
DH公鑰就是Pubkey
,簽名就是Signatrue
,DH參數就是由Curve Type
、Named Curve
、Pubkey
組成的。
該信息是用於密鑰交換。由於https在真正的通訊階段,是經過對稱加密來對內容進行加密的,那麼對稱加密的密鑰交換的安全性就顯得很是重要,若是安全的保證客戶端和服務端都能得到這個對稱加密的密鑰就是該信息須要作的事情了。
具體的細節能夠自行查看DH算法的流程,這裏也提供一些資料:
服務器發送完上述信息以後,會馬上發送該信息,而後等到客戶端的響應。
該信息的主要做用兩點:
在接受到服務器的Server Hello Done信息以後,客戶端應該馬上發送該信息。該信息的主要做用是協商出預備主密鑰,通常有兩種方式:
經過抓包信息能夠看出,這裏使用的是第二種方式。由於這裏只將一個DH公鑰發送給了服務端。
具體客戶端是如何計算出該DH公鑰的能夠參考DH算法的實現流程,參考連接已經在上面給出。
最終,客戶端和服務器會計算出相同的預備主密鑰。而該預備主密鑰就做爲第三個隨機數。
咱們知道前面已經獲得了兩個隨機數了,最後客戶端和服務端會根據這三個隨機數計算出對稱加密所須要的密鑰,由於該密鑰是在各自的本地進行計算的,並無經過網絡傳輸,因此該密鑰是安全的。
固然,咱們只須要保證第三個隨機數是安全的那麼對稱密鑰纔是安全的,而DH算法就是用於獲得這第三個隨機數,至於DH算法如何保證第三個隨機數的安全性,請自行查閱。
該協議並非握手協議中的一部分。客戶端和服務端在計算出密鑰以後,接下來通知對端,後續的信息都須要TLS記錄層協議加密保護了。
也就是該信息用於告訴對方,我已經計算好須要使用的對稱密鑰了,咱們接下來的通訊都須要使用該密鑰進行加密以後再發送。
須要注意的是,發送該信息的一方並不知道對方是否已經計算出密鑰。通常由客戶端先行發送該信息。
該信息是第一個由TLS記錄層協議進行加密保護的信息,雙方須要驗證對方發送的Finished信息,保證協商的密鑰是可用的,保證協商過程當中,沒有被篡改。
驗證該verify Data的內容,包括三部分的內容:
其實在客戶端與服務端協商處理的密碼套件中,是同時包含了多個算法的.
拿咱們文章中協商出的密碼套件來講:
密碼套件 | 密鑰協商算法 | 身份驗證算法 | 加密算法 | Hash 算法 | 協議 |
---|---|---|---|---|---|
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | ECDHE | RSA | AES-128-GSM | SHA256 | TLS |
https是如何保證保密性的呢,咱們知道對稱密碼是經過ECDHE算法協商出一個隨機數,而後經過隨機數1,隨機數2,隨機數3經過一個計算方法一塊兒計算出一個對稱密鑰,由於該密鑰是在本地計算的,不通過網絡傳輸,因此該對稱密鑰是安全的。
而後每次的通訊均可以使用該對稱密鑰進行加密和解密了。
可是DH算法如何保證發送的DH公鑰是客戶端發送的呢?這裏也遇到了跟CA證書同樣的問題,如何保證CA證書是有效的呢?在CA證書中是經過使用CA的私鑰對用戶的CRS信息+CA的信息+用戶提供的公鑰進行一個數字簽名,只要瀏覽器可使用公鑰進行解密,那麼就等於該證書是有效的。
一樣,DH算法也是如此,發送DH的信息時,服務端會對DH參數和DH公鑰使用私鑰進行數字簽名,只要客戶端可使用公鑰進行解密,那麼就說明該信息是有效的。客戶端發送的信息也是如此。
這裏提供一個參考文章:DH算法如何防護中間人攻擊
瀏覽器是如何對CA證書進行驗證的?
首先咱們先要知道CA證書是如何產生的,首先是申請證書的服務方S須要向第三方CA機構提供CSR(Certificate Signing Request 證書籤名請求),第三方機構收到該請求以後,會對該請求中的信息進行覈對,線上線下都會進行驗證,好比,提供的域名是否屬於服務方,地址是否正確等等,只有第三方機構認爲你提供的信息都是準確的,它就會根據(你提供的信息+CA機構的信息+公鑰)生成一個信息,而後會對該信息進行一個信息摘要,而後使用CA私鑰對該信息摘要進行一個數字簽名。而後再將生成的信息、數字簽名一塊兒生成一個數字證書發佈給服務方。
瀏覽器校驗證書的流程:首先在本地電腦尋找一個發佈該證書的CA機構的根證書,根證書都是預先安裝在操做系統上的,若是有則會對證書上的內容進行驗證,好比域名是否一致,證書是否過時等,而後使用CA機構的公鑰對該數字簽名進行解密,若是解密成功,則說明該證書是有效的。
客戶端如何保證CA證書是完整的,而沒有被別人篡改過呢?好比第三方截取到證書以後,對證書的內容進行了修改。
咱們知道在生成證書的時候,會對信息生成信息摘要,客戶端只要拿到CA證書以後,對證書中的信息進行一次信息摘要的生成,而後與使用數字簽名解密出來的內容進行對比,就能夠知道證書中的內容是否被篡改過。
假如中間人獲取到了CA證書,並修改了證書中的域名,可是此時它沒有CA機構的私鑰,因此它沒法獲得一個新的簽名,而後客戶端收到該篡改的證書後,經過私鑰解密出來一個原證書信息的摘要,而且客戶端對收到的證書內容生成信息摘要,發現兩個信息不一致,就會終止通訊,防止信息泄露。
假如中間人也有一個CA機構頒發的合法的證書,中間人攔截到服務端發送的證書,並將本身的證書發送給客戶端,此時客戶端就會使用中間人證書的公鑰進行通訊。
其實該狀況是不會發生的,由於在驗證的過程當中會驗證域名,若是訪問的域名與證書中的域名不一致就會提示不安全的連接。可是若是中間人可使用你的域名去申請到證書,那就另當別論了,可是這也不會發生,由於證書申請是須要進行信息覈實的,並非能夠隨意申請的。
其實這只是一個性能問題,由於hash值相對於CA證書的信息來講是比較短的值,對該值進行加密和解密都會比較快。一般在生成證書的時候也不會在意這些時間,可是在瀏覽器進行解密時,若是時間過長,用戶可就等不了那麼長的時間了。
其實在CA機構中的公鑰都是內置於操做系統的,內置於操做系統中的公鑰必定是可信的。若是連他們都不信,那麼咱們就沒法完成CA證書的驗證了。
而且CA證書並不必定就是由CA機構頒發的,也能夠由CA機構受權的代理商進行發佈,也就是說CA機構對它受權的代理商也是信任的。因此咱們通常拿到的都是一個三級證書,一級證書就是CA機構的根證書,二級證書就是CA機構受權的代理商的證書,三級證書就是咱們本身的證書,這三個證書構成了一個證書鏈。
咱們看到掘金中的證書,就是一個三級的證書鏈。
若是每一次https的請求都須要進行TLS的握手,TLS的握手那麼複雜,勢必會對通訊帶來較大的延時,這對注重用戶體驗的網站來講,是不可接受的。那麼有什麼辦法能夠避免這種狀況嗎?
實際上是經過一個Session Identifier(會話標識符),該Session ID是 TLS 握手中生成的 Session ID。服務端能夠將 Session ID 協商後的信息存起來,瀏覽器也能夠保存 Session ID,並在後續的 Client Hello 握手中帶上它,若是服務端能找到與之匹配的信息,就能夠完成一次快速握手。