轉載自:https://mp.weixin.qq.com/s/UiGEzXoCn3F66NRz_T9crA 原創: 濤哥 coding濤 6月9日算法
做者對https 解釋的入目三分啊瀏覽器
(全文太長,太懶不想看,-_-b 那就直接拉到底部看總結 )安全
前面的文章中,提到了,https是在TCP協議與http之間加了一個控制安全傳輸的SSL協議,也就是說,直接運行在TCP之上的HTTP是普通的HTTP,運行在SSL/TLS上的HTTP則是HTTPS。這幾個協議在計算機網絡的OSI七層模型中的位置以下表所示:服務器
層級層名經常使用協議網絡
7應用層HTTP/HTTPS、FTP、Socket、Telnet、SSH、SMTP、POP三、DHCP、DNS、NFS、SNMP併發
6表示層XDR、LPP加密
5會話層SSL/TLS、LDAP/DAP、RPCurl
4傳輸層TCP、UDPspa
3網絡層IP、OSPF、ICMP、計算機網絡
2數據鏈路層以太網、令牌環、PPP、PPTP、L2TP、ARP、ATMP
1物理層物理線路、光纖、無線電
客戶端執行https請求時,須要由TCP協議創建和釋放鏈接。這就涉及TCP協議的三次握手和四次揮手。
注意:咱們可能會常常看到「HTTP的三次握手」這個說法,其實這種說法不許確,HTTP是沒有什麼三次握手的,這個其實指的就是TCP的三次握手。
1、TCP的三次握手(不想了解,可跳過)
TCP經過三次握手,創建鏈接
第一次:客戶端發送一個惟一的數據包(SYNJ)給服務器,請求創建鏈接
第二次:服務器收到客戶端的請求後,生成一個SYN J的迴應包(ack J+1)和一個新的數據包(SYN K),發給客戶端
第三次:客戶端收到服務器返回的兩個包後,針對服務器的SYN K包生成一個迴應包(ack K+1),併發送給服務器。至此,完成3步握手。這個過程,相似咱們在信號很差的時候打電話的過程:
「喂,能聽到我說話嗎」
「我能聽到,你能聽到我嗎」
「能聽到」
...
注意,這裏「能聽到」包含了「聽到」和「聽懂」的兩層意思。想象一下,你用中文,對方給你回了一個你聽不懂的俄文,這個通話也就沒有必要進行下去了。
2、TCP的四次揮手(不想了解,可跳過)
TCP協議是一個全雙工協議(能夠同時進行收發),經過四次揮手關閉鏈接。
簡單理解:
第一步:客戶端發送FIN(M)報文給服務器,告訴對方,「個人數據發完了」。
第二步:服務器收到FIN(M)報文後,回給客戶端一個ack(M+1)報文,告訴客戶端,「好,我知道了」。
第三步:服務器發一個FIN(N)報文給客戶端,告訴對方,「個人數據也發完了」。
第四步:客戶端迴應ack(N+1),告訴服務器,「好,我知道了」,至此,鏈接結束。
這個過程相似兩我的打完電話的結束過程。
A:我說完了
B:哦
B想了一下,也沒什麼要說的
B:我也說完了
A:好
通話結束,雙方掛電話
3、HTTPS單向驗證
TCP鏈接創建好後,對於HTTP而言,服務器就能夠發數據給客戶端。可是對於HTTPS,它還要運行SSL/TLS協議,SSL/TLS協議分兩層,第一層是記錄協議,主要用於傳輸數據的加密壓縮;第二層是握手協議,它創建在第一層協議之上,主要用於數據傳輸前的雙方身份認證、協商加密算法、交換密鑰。
HTTPS驗證過程就是SSL握手協議的交互過程。「HTTPS驗證」這個說法其實不許確的,應該是「SSL驗證」,這兩種說法網上都能看到。
咱們先從簡單點的單向驗證開始解釋:
第一步:客戶端發起ClientHello
客戶端向指定域名的服務器發起https請求,請求內容包括:
1)客戶端支持的SSL/TLS協議版本列表
2)支持的對稱加密算法列表
3)客戶端生成的隨機數A
第二步:服務端迴應SeverHello
服務器收到請求後,迴應客戶端,迴應的內容主要有:
1)SSL/TLS版本。服務器會在客戶端支持的協議和服務器本身支持的協議中,選擇雙方都支持的SSL/TLS的最高版本,做爲雙方使用的SSL/TLS版本。若是客戶端的SSL/TLS版本服務器都不支持,則不容許訪問
2)與1相似,選擇雙方都支持的最安全的加密算法。
3)從服務器密鑰庫中取出的證書
4)服務器端生成的隨機數B
第三步:客戶端迴應
客戶端收到後,檢查證書是否合法,主要檢查下面4點:
一、檢查證書是否過時
二、檢查證書是否已經被吊銷。
有CRL和OCSP兩種檢查方法。CRL即證書吊銷列表,證書的屬性裏面會有一個CRL分發點屬性,以下圖所示(CSDN的證書),這個屬性會包含了一個url地址,證書的簽發機構會將被吊銷的證書列表展示在這個url地址中;OCSP是在線證書狀態檢查協議,客戶端直接向證書籤發機構發起查詢請求以確認該證書是否有效。
三、證書是否可信。
客戶端會有一個信任庫,裏面保存了該客戶端信任的CA(證書籤發機構)的證書,若是收到的證書籤發機構不在信任庫中,則客戶端會提示用戶證書不可信。
若客戶端是瀏覽器,各個瀏覽器都會內置一些可信任的證書籤發機構列表,在瀏覽器的設置中能夠看到。
若是不在信任表中,則瀏覽器會出現相似下面的警告頁面,提示你不安全。(固然,你能夠選擇繼續訪問)
若客戶端是程序,例如Java中,須要程序配置信任庫文件,以判斷證書是否可信,若是沒設置,則默認使用jdk自帶的證書庫(jre\lib\security\cacerts,默認密碼changeit)。若是證書或簽發機構的證書不在信任庫中,則認爲不安全,程序會報錯。(你能夠在程序中設置信任全部證書,不過這樣並不安全)。
四、檢查收到的證書中的域名與請求的域名是否一致。
若客戶端是程序,這一項可配置不檢查。若爲瀏覽器,則會出現警告,用戶也能夠跳過。
證書驗證經過後,客戶端使用特定的方法又生成一個隨機數c,這個隨機數有專門的名稱「pre-master key」。接着,客戶端會用證書的公鑰對「pre-master key」加密,而後發給服務器。
第四步,服務器的最後迴應
服務器使用密鑰庫中的私鑰解密後,獲得這個隨機數c。此時,服務端和客戶端都拿到了隨機數a、b、c,雙方經過這3個隨機數使用相同的DH密鑰交換算法計算獲得了相同的對稱加密的密鑰。這個密鑰就做爲後續數據傳輸時對稱加密使用的密鑰。
服務器迴應客戶端,握手結束,能夠採用對稱加密傳輸數據了。
這裏注意幾點:
一、整個驗證過程,折騰了半天,實際上是爲了安全地獲得一個雙方約定的對稱加密密鑰,固然,過程當中也涉及一些身份認證過程。既然剛開始時,客戶端已經拿到了證書,裏面包含了非對稱加密的公鑰,爲何不直接使用非對稱加密方案呢,這是由於非對稱加密計算量大、比較耗時,而對稱加密耗時少。
二、對稱加密的密鑰只在此次鏈接中斷前有效,從而保證數據傳輸安全。
三、爲何要用到3個隨機數,1個不行嗎?這是由於客戶端和服務端都不能保證本身的隨機數是真正隨機生成的,這樣會致使數據傳輸使用的密鑰就不是隨機的,時間長了,就很容易被破解。若是使用客戶端隨機數、服務端隨機數、pre-master key隨機數這3個組合,就能十分接近隨機。
四、什麼是信任庫和密鑰庫。信任庫前面已經說了,它是用來存放客戶端信任的CA的證書。在程序交互中,須要確保你訪問的服務器的證書在你的信任庫裏面。密鑰庫是用來存放服務器的私鑰和證書。
五、中間人攻擊問題。前面過程說明中,有一點,客戶端是驗證有問題的時候,是能夠選擇繼續的。對瀏覽器而言,用戶能夠選擇繼續訪問;對程序而言,有些系統爲了處理簡單,會選擇信任全部證書,這樣就給中間人攻擊提供了漏洞。
中間人攻擊時,它想辦法攔截到客戶端與服務器之間的通訊。在客戶端向服務器發信息時,中間人首先假裝成客戶端,向真正的服務器發消息,得到真正的證書,接着假裝成服務器將本身的僞證書發給客戶端。服務器向客戶端發消息時,中間人假裝成客戶端,接收消息,而後再假裝成服務器向客戶端發消息。最後驗證過程完成後,客戶端的真實對稱密鑰被中間人拿到,而真正的服務器拿到的是中間人提供的僞密鑰。後續數據傳輸過程當中的數據就會被中間人竊取。
4、HTTPS雙向驗證
單向驗證過程當中,客戶端會驗證本身訪問的服務器,服務器對來訪的客戶端身份不作任何限制。若是服務器須要限制客戶端的身份,則能夠選擇開啓服務端驗證,這就是雙向驗證。從這個過程當中咱們不難發現,使用單向驗證仍是雙向驗證,是服務器決定的。
通常而言,咱們的服務器都是對全部客戶端開放的,因此服務器默認都是使用單向驗證。若是你使用的是Tomcat服務器,在配置文件server.xml中,配置Connector節點的clientAuth屬性便可。若爲true,則使用雙向驗證,若爲false,則使用單向驗證。若是你的服務,只容許特定的客戶端訪問,那就須要使用雙向驗證了。
雙向驗證基本過程與單向驗證相同,不一樣在於:
1)第二步服務器第一次迴應客戶端的SeverHello消息中,會要求客戶端提供「客戶端的證書」
2)第三步客戶端驗證完服務器證書後的迴應內容中,會增長兩個信息:
一、客戶端的證書
二、客戶端證書驗證消息(CertificateVerifymessage):客戶端將以前全部收到的和發送的消息組合起來,並用hash算法獲得一個hash值,而後用客戶端密鑰庫的私鑰對這個hash進行簽名,這個簽名就是CertificateVerify message
說明:這裏關於客戶端私鑰的使用,網上有不少文章認爲:在協商對稱加密方案時,服務端先用客戶端公鑰加密服務器選定的對稱加密方案,客戶端收到後使用私鑰解密獲得。首先,對稱加密方案就那麼幾種,逐個試試就能試出來,不必爲了這個增長一個客戶端和服務端的交互過程。而這裏關於CertificateVerify message的說法參考了維基百科關於「Transport Layer Security」一文中"Client-authenticated TLS handshake"的描述。連接:https://en.wikipedia.org/wiki/Transport_Layer_Security#Client-authenticated_TLS_handshake
3)服務器收到客戶端證書後:
a)確認這個證書是否在本身的信任庫中(固然也會校驗是否過時等信息),若是驗證不經過則會拒絕鏈接;
b)用客戶端證書中的公鑰去驗證收到的證書驗證消息中的簽名。這一步的做用是爲了確認證書確實是客戶端的。
因此,在雙向驗證中,客戶端須要用到密鑰庫,保存本身的私鑰和證書,而且證書須要提早發給服務器,由服務器放到它的信任庫中。
5、總結一下:
一、單向驗證中,若是是你客戶端,你須要拿到服務器的證書,並放到你的信任庫中;若是是服務端,你要生成私鑰和證書,並將這兩個放到你的密鑰庫中,而且將證書發給全部客戶端。
二、雙向驗證中,若是你是客戶端,你要生成客戶端的私鑰和證書,將它們放到密鑰庫中,並將證書發給服務端,同時,在信任庫中導入服務端的證書。若是你是服務端,除了在密鑰庫中保存服務器的私鑰和證書,還要在信任庫中導入客戶端的證書。
三、再次強調,使用單向驗證仍是雙向驗證,是服務器決定的。
四、https的驗證過程,不論是單向仍是雙向,只有四步,網上不少關於https驗證過程的文章中,寫了來來回回七八上十步。要真是這樣,訪問一個https地址,時間全花在了交互上了。
做者:神仙甦醒
連接:https://www.jianshu.com/p/119c4dbb7225
來源:簡書
簡書著做權歸做者全部,任何形式的轉載都請聯繫做者得到受權並註明出處。
SSL握手:
1.客戶單發送hello,這個hello裏面有:我是IE瀏覽器,我支持什麼算法des等,SSL/TLS協議版本,隨機數A。
2.server回hello包,選擇一個算法des(加密數據使用), server回證書(證書有server的公鑰),隨機數B
3.客戶端驗證證書,隨機數C,用公鑰加密,發送證書。
4. 服務器驗證證書,服務端用私鑰解密獲得C,客戶端和服務端都有abc3個隨機數了。使用abc3個隨機數生成數據對稱加密密鑰。如今密鑰和加密算法都選擇好了,模式變動,後面的數據都開始加密。
隨機數是在第一個請求就開始傳輸了,非對稱加密(客戶端用證書公鑰加密隨機數C服務端用證書私鑰解密隨機數C)。數據加密要密鑰和加密算法對稱加密。
客戶端模式變動:就是以前沒有加密,後面的數據包都要加密了,你去解密。服務端模式變動:就是以前沒有加密,後面的數據包都要加密了,你去解密。