SSL和TLS都是加密協議,旨在基於不安全的基礎設施提供安全通訊,好比能夠用ssl協議對HTTP協議進行加密變成HTTPS。算法
ssl協議在網絡分層中處於表示層。api
SSL協議是一種記錄協議,協議組成包括:瀏覽器
1字節的content type:握手協議報文、數據協議報文、告警協議報文;安全
2字節的version:ssl3.0、tls1.0、tls1.一、tls1.2;服務器
1字節的data length:表示負載數據的大小;網絡
負載數據:ssl協議的負載數據。能夠是握手數據或者是加密後的應用層數據。socket
SSL協議由網景(Netscape Communications Corporation)公司開發,第一個版本從未發佈。網站
第二版本於1994年11月發佈,第一次部署是在Netscape Navigator1.1瀏覽器上,發行於1995年3月。可是因爲SSL2.0的開發基本上沒有與Netscape之外的安全專家進行商討,因此有嚴重的缺點,最終退出歷史舞臺。加密
第三版本於1995年年末發佈,SSL3.0是徹底從新設計的協議,一直沿用到今天。url
1996年5月,TLS工做組成立,開始將SSL從Netscape遷移至IETF。因爲Microsoft和Netscape當時正在爲Web的統治權爭得不可開交,整個遷移過程進行得很是緩慢、艱難。最終,TLS 1.0於1999年1月問世。
2006年4月,下一個版本TLS 1.1才問世。
2008年8月,TLS 1.2發佈。
2016年年中,TLS 1.3草案已經經歷了15次迭代,基本肯定了版本號和協商。
2017年2月,Chrome和Firefox都開始爲其客戶提供TLS 1.3。
ssl握手的過程及其複雜,下面在說ssl握手以前,先看一個通訊過程加密的演化過程。若是能理解了這個過程,那麼ssl協議的握手也就不那麼複雜。在這過程當中會引入一些密碼學的基本概念。
最典型的明文通訊就是咱們你們都熟知的http協議。可是明文通訊會存在一下問題:
因此明文通訊是很不安全的,那麼咱們就把通訊數據進行加密吧,以密文的方式進行傳輸,對數據進行加密有兩種方式:對稱加密和非對稱加密。
由上述的定義來看,非對稱加密比對稱加密的強加密強度要高,那麼咱們接下來就用非對稱加密的方式對數據進行加密。
在這個階段中,前三個報文任然是明文,可是第四個報文"你好,我是服務器"用服務器本身的私鑰進行加密。客戶端擁有服務器的公鑰,收到報文後,用公鑰進行解密,就拿到了解密後的報文"你好,我是服務器"。
因爲公鑰只能解密用私鑰加密的數據,而私鑰只有服務器擁有。因此客戶端在成功用服務器的公鑰解密後,就對服務器的身份進行了初步的認證:你是我擁有公鑰的服務器。注意在這,客戶端只能證實你是我擁有公鑰的服務器。至於這個是否是真正的服務器,還並不能徹底肯定。
由於到目前爲止客戶端還沒法證實本身擁有的公鑰是真正服務器的公鑰。這個認證過程在後續展開。可是最起碼從上面的過程看來,咱們已經成功的對服務器發出的報文進行了非對稱加密。而後再接下來看一下後續的通信過程:
在這個通訊過程當中,在完成對服務器的認證後,客戶端把''把個人餘額發給我看看"用服務器的公鑰進行加密。發給服務器,因爲只有服務器擁有私鑰,因此只有服務器可以解密這個報文。而後將客戶端餘額用私鑰進行加密發給客戶端。
在這最後一個報文出現了問題。由於,服務器是用本身私鑰對餘額信息進行加密的。因此只要有服務器的公鑰,就能解密。而服務器的公鑰又是對外公開的,因此這個方向的報文就再也不安全。爲了解決這個問題,咱們又引入了對稱加密。
在這個階段中,客戶端在確認了服務器的身份後,客戶端本身選擇一個對稱加密算法和一個密鑰,把這個對稱加密算法和密鑰一塊兒用公鑰加密後發送給服務器。因爲對稱加密算法和密鑰是用公鑰加密的,就算這個加密後的內容被黑客截獲了,因爲沒有私鑰,黑客也無從知道對稱加密算法和密鑰的內容。而後後續的通訊內容就用對稱加密的密鑰進行加密,這樣後續的報文就不會被人解密。
可是在第二階段就說過,非對稱加密時對服務器的認證是不徹底的,只能證實,當前服務器是我擁有公鑰的服務器。而不能徹底證實你就是我要通訊的服務器。由於還沒法證實,我擁有的公鑰是我客戶端要鏈接服務器
的公鑰。因此咱們只要能保證當前的公鑰是真正的服務器的公鑰,客戶端就能徹底認證服務器。也就是說服務器如何正確的把本身的公鑰發給客戶端。因此在這裏又引入了數字證書。服務器把本身的公鑰放在證書裏,而後在通訊時把證書發給客戶端。
那麼爲何不直接把公鑰發給客戶端呢?
由於客戶端會接受的任何人的公鑰,不能證實當前收到的公鑰就是真正服務器的公鑰,黑客能夠本身生成一個公鑰發給客戶端,冒充服務器完成上述的過程。
那麼爲何證書就能證實當前的證書的公鑰是真正服務器的呢?下面來看下證書的組成。
◆Issuer (證書的發佈機構):指出是什麼機構發佈的這個證書,也就是指明這個證書是哪一個公司建立的(只是建立證書,不是指證書的使用者)。
◆Valid from , Valid to (證書的有效期):證書的有效時間,或者說證書的使用期限。 過了有效期限,證書就會做廢,不能使用了。
◆Public key (公鑰):使用者的公鑰。
◆Subject (主題):這個證書是發佈給誰的,或者說證書的全部者,通常是某我的或者某個公司名稱、機構的名稱、公司網站的網址等。
◆Signature algorithm (簽名所使用的算法):就是指的這個數字證書的數字簽名所使用的加密算法,這樣就可使用證書發佈機構的證書裏面的公鑰,根據這個算法對指紋進行解密。
◆Thumbprint, Thumbprint algorithm (指紋以及指紋算法):用來保證證書的完整性的。
當前證書的合法性,也就是當前證書裏的公鑰是屬於證書的擁有者的。這一特性是由證書的發佈機構(CA)來證實的。在現實中CA擁有很高的權威性,可以受到廣大範圍的信任。CA在給網站頒發證書前,會在現實中對網站進行各類資質的調查。
若是調查的結果符合他的標準,CA機構纔會頒發給網站證書,表示我能證實你是能夠被信任的網站。固然這個信任也不是永久的,這就是證書的有效期。CA只能證實在這個有效期內,這個網站是被信任的。因此客戶端,只要可以信任這個CA,那麼這個CA
信任的網站也是能夠信任的。證書就是經過這種間接證實的方式來對服務器端進行認證的。
可是在這仍是存在一個問題,客戶端在收到證書後,是如何肯定當前證書是信任的CA簽發的呢?下面咱們來看一下客戶端校驗證書的過程:
在CA頒發證書時,會用CA本身的私鑰進行簽名,並把簽名後的指紋放在證書裏。簽名的算法也會用CA的私鑰進行加密放在證書中。而CA的公鑰是放在CA本身的證書裏,CA的證書會直接寫在操做系統中。因此客戶端能從操做系統中
拿到CA的公鑰從而對當前收到的server證書裏的簽名算法進行解密,從而最後計算出指紋,與證書中的指紋進行比對,判斷證書的合法性。
可是在實際中,通常網站不是向客戶端發送一個證書,而是一個證書鏈。
在證書鏈中,第一個證書是最終的實體證書,也就是要訪問網站的證書,這個網站的證書是用另外一箇中間證書進行簽發的,可能這個中間證書不是當前客戶端可以信任的(沒寫進操做系統),可是這個中間證書是由一個根證書進行簽發的,而只要客戶端的操做系統中有根證書的公鑰。
那麼客戶端就能信任根證書,從而信任根證書籤發的中間證書,也就可以信任中間證書籤發的最終實體證書。 其中,中間證書可能有多個。也就是說在一個證書鏈中,只要根證書是信任的,那麼這個證書鏈中的全部證書都是信任的。
到目前爲止,咱們經過證書鏈,已經解決了通訊加密中的認證問題,如今通訊過程就演化到了第四階段。
到在這個階段爲止就已經解決了對明文的加密和對服務器端的認證問題。咱們所推演出的第四階段的加密通訊過程其實就是RSA認證的過程。經過這個過程你們應該就已經知道對一個通訊過程進行加密的關鍵點是加密密鑰的傳輸,服務器端的認證。
總結下,在上述的演化過程當中,咱們用對稱加密的方式加密要傳輸的數據。而爲了保證密鑰的安全性,咱們用非對稱加密的方式傳輸對稱加密的密鑰,而非對稱加密涉及到的服務器端的認證,咱們用證書鏈的方式來解決。
根據上述的演化過程,下面來看下SSL和TLS的的握手過程。
在握手過程當中的報文介紹以下:
ClientHello報文中主要包含如下內容:
客戶端支持的最高tls版本;
支持的加密套件的列表;
若是過支持報文壓縮的話,支持的壓縮算法列表;
一個客戶端產生的32字節的隨機數,用來計算密鑰
ServerHello報文中主要包含如下內容:
服務器選定的本次通訊所採用的ssl版本,通常是客戶端和服務器支持的最高版本的較小那個,保證雙方都支持。
服務器選定的本次通訊所採用的加密套件,客戶端和服務器端都支持的加密套件。
若是過支持報文壓縮的話,選定的壓縮算法;
一個服務器端生成的32 字節的隨機數。
Certificate:
可選報文,發送服務器端的證書鏈。
ServerKeyExchange:
可選報文,發送用於加密的其餘數據。
ServerHelloDone:
服務器端在把用於握手的全部數據發送完畢後會發送這個報文。
ClientKeyExchange:
客戶端根據選定的加密套件,提供加密套件加密須要的客戶端的參數。
ChangeCipherSpec:
這個報文並不屬於ssl協議,當客戶端生成用於後續加密的密鑰後會發送這個報文給服務器,告知我已準備好。可進行後續的機密通訊。服務器在生成密鑰後也會發送這個報文,告知客戶端,我也準備好了。
finished:
這個報文中存在 verify_data,是用主密鑰、finishedlabel(一個特定的字符串)和以前握手過程的全部報文(不包含ChangeCipherSpec)爲參數生成的一個隨機hash值,用來驗證握手的完整性。
在握手過程當中對稱加密密鑰的生成過程:
在clienthello和serverhello傳輸生成的兩個隨機數和協商的加密套件,服務器利用ServerKeyExchange傳輸用於加密的其餘服務器端參數。客戶端利用clientkeyexchange 提供加密套件須要的客戶單端參數。在這時,客戶端和服務器端都保有用於生成主密鑰 master_secret的全部參數。在客戶端和服務器端各自生成主密鑰master_secret。再由主密鑰master_secret、兩個隨機數的和、字符串"key expansion"進一步生成最終的密鑰key_block。key_block是後續對稱加密的密鑰。
當選用不一樣的加密套件時,ssl握手階段的報文是有區別的。下面簡單說下以RSA認證的SSL握手流程和密鑰生成的過程。
首先客戶端在clienthello報文中提供一個32 字節的隨機數。
服務器在serverhello報文中提供一個32字節的隨機數。
服務器把本身的證書鏈放在Certificate報文中發給客戶端,選用RSA認證時服務器端不會發送ServerKeyExchange報文。而是在發送完證書鏈後發送serverhellodone。
客戶端在收到服務器產生的隨機數和證書鏈後,會在本地用clienthello報文中的隨機數和serverhello中的隨機數生成一個預主密鑰pre_master_secret,把預祝密鑰用服務器公鑰加密在ClientKeyExchange報文中發給服務器。
客戶端進一步以預主密鑰pre_master_secret、字符串"master secret"、兩個隨機數的和爲參數再生成一個hash值爲主密鑰master_secret。在以主密鑰master_secret和兩個隨機數的和、字符串"key expansion"爲參數生成一個hash值,爲最終的密鑰key_block,用於後續的對稱加密。
當客戶端生成密鑰key_block後,會發送ChangeCipherSpec報文,通知服務器本身能夠進行對稱加密了。
而後,客戶端以主密鑰master_secret、finshedlabel(一個特定的字符串)和以前握手階段的全部報文數據(不包含ChangeCipherSpec)爲參數生成一個hash值爲verify_data,而後對verify_data用生成的密鑰進行對稱加密放在finished報文發給服務器。
服務器在收到客戶端發出的ClientKeyExchange報文後,用本身的私鑰進行解密。拿到預主密鑰pre_master_secret,用預主密鑰pre_master_secret、兩個隨機數的和、字符串"master secret"爲參數生成hash值爲主密鑰master_secret,再用master_secret、兩個隨機數的和、"key expansion"爲參數生成hash值爲最終的密鑰key_block。
當服務器端也生成密鑰後會發送ChangeCipherSpec告知客戶端本身能夠進行對稱加密了。
而後服務器在收到客戶端發出的finished報文後,用本身生成的密鑰key_block解密。解密後拿到verify_data,進行驗證。驗證的方式是服務器本身按照相同的方式生成一個hash值與verify_data進行比較。如過相同,則證實以前的握手報文是完整的,沒有被篡改過。
服務器用本身的主密鑰master_secret、finishedlabel(一個特定的字符串)和以前握手數據報文(不包含ChangeCipherSpec)生成一個hash值verify_data,把verify_data用服務器生成的密鑰key_block進行加密,在finished報文發給客戶端。
客戶端在收到服務器端發的finishe報文解密後校驗verify_data來驗證握手階段的完整性。
注意:
由於在生成密鑰過程當中參數都是相同的,因此最後生成的hash值密鑰key_block也是相同的。