https握手過程及相關知識

灰s發表於2017-12-22

一、Https握手過程

Https.png

圖片的握手過程和文字並不是完全對應的,文字敘述的更具體一些。 圖片僅供參考。

1. client_hello

客戶端發起請求,以明文傳輸請求資訊,包含版本資訊,加密套件候選列表,壓縮演算法候選列表,隨機數,擴充套件欄位等資訊,相關資訊如下:
- 支援的最高TSL協議版本version,從低到高依次 SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2,當前基本不再使用低於 TLSv1 的版本
- 客戶端支援的加密套件 cipher suites 列表, 每個加密套件對應前面 TLS 原理中的四個功能的組合:認證演算法 Au (身份驗證)、金鑰交換演算法 KeyExchange(金鑰協商)、對稱加密演算法 Enc (資訊加密)和資訊摘要 Mac(完整性校驗)
- 支援的壓縮演算法 compression methods 列表,用於後續的資訊壓縮傳輸
- 隨機數 random_C,用於後續的金鑰的生成
- 擴充套件欄位 extensions,支援協議與演算法的相關引數以及其它輔助資訊等,常見的 SNI 就屬於擴充套件欄位,後續單獨討論該欄位作用
複製程式碼

2. server_hello+server_certificate+sever_hello_done

- server_hello, 服務端返回協商的資訊結果,包括選擇使用的協議版本 version,選擇的加密套件 cipher suite,選擇的壓縮演算法 compression method、隨機數 random_S 等,其中隨機數用於後續的金鑰協商
- server_certificates, 伺服器端配置對應的證書鏈,用於身份驗證與金鑰交換
- server_hello_done,通知客戶端 server_hello 資訊傳送結束
複製程式碼

3. 證書校驗

客戶端驗證證書的合法性,如果驗證通過才會進行後續通訊,否則根據錯誤情況不同做出提示和操作,合法性驗證包括如下:
- [[證書鏈]](http://blog.csdn.net/hherima/article/details/52469488)的可信性 trusted certificate path,方法如前文所述
- 證書是否吊銷 revocation,有兩類方式離線 CRL 與線上 OCSP,不同的客戶端行為會不同
- 有效期 expiry date,證書是否在有效時間範圍
- 域名 domain,核查證書域名是否與當前的訪問域名匹配,匹配規則後續分析
複製程式碼

4. client_key_exchange+change_cipher_spec+encrypted_handshake_message

- client_key_exchange,合法性驗證通過之後,客戶端計算產生隨機數字 Pre-master,並用證書公鑰加密,傳送給伺服器
- 此時客戶端已經獲取全部的計算協商金鑰需要的資訊:兩個明文隨機數 random_C 和 random_S 與自己計算產生的 Pre-master,計算得到協商金鑰
enc_key=Fuc(random_C, random_S, Pre-Master)
- change_cipher_spec,客戶端通知伺服器後續的通訊都採用協商的通訊金鑰和加密演算法進行加密通訊
- encrypted_handshake_message,結合之前所有通訊引數的 hash 值與其它相關資訊生成一段資料,採用協商金鑰 session secret 與演算法進行加密,然後傳送給伺服器用於資料與握手驗證
複製程式碼

5. change_cipher_spec+encrypted_handshake_message

- 伺服器用私鑰解密加密的 Pre-master 資料,基於之前交換的兩個明文隨機數 random_C 和 random_S,計算得到協商金鑰:enc_key=Fuc(random_C, random_S, Pre-Master)
- 計算之前所有接收資訊的 hash 值,然後解密客戶端傳送的 encrypted_handshake_message,驗證資料和金鑰正確性
- change_cipher_spec, 驗證通過之後,伺服器同樣傳送 change_cipher_spec 以告知客戶端後續的通訊都採用協商的金鑰與演算法進行加密通訊
- encrypted_handshake_message, 伺服器也結合所有當前的通訊引數資訊生成一段資料並採用協商金鑰 session secret 與演算法加密併傳送到客戶端
複製程式碼

6. 握手結束

客戶端計算所有接收資訊的 hash 值,並採用協商金鑰解密 encrypted_handshake_message,驗證伺服器傳送的資料和金鑰,驗證通過則握手完成
複製程式碼

7. 加密通訊

開始使用協商金鑰與演算法進行加密通訊
複製程式碼

8. 注意:

- 伺服器也可以要求驗證客戶端,即雙向認證,可以在過程2要傳送 client_certificate_request 資訊,客戶端在過程4中先傳送 client_certificate與certificate_verify_message 資訊,證書的驗證方式基本相同,certificate_verify_message 是採用client的私鑰加密的一段基於已經協商的通訊資訊得到資料,伺服器可以採用對應的公鑰解密並驗證
- 根據使用的金鑰交換演算法的不同,如 ECC 等,協商細節略有不同,總體相似
- sever key exchange 的作用是 server certificate 沒有攜帶足夠的資訊時,傳送給客戶端以計算 pre-master,如基於 DH 的證書,公鑰不被證書中包含,需要單獨傳送
 -  change cipher spec 實際可用於通知對端改版當前使用的加密通訊方式,當前沒有深入解析
- alter message 用於指明在握手或通訊過程中的狀態改變或錯誤資訊,一般告警資訊觸發條件是連線關閉,收到不合法的資訊,資訊解密失敗,使用者取消操作等,收到告警資訊之後,通訊會被斷開或者由接收方決定是否斷開連線
複製程式碼

二、相關的一些名詞解釋

1. RTT(Round Trip Time)

表示客戶端從發出一個請求資料,到接收到響應資料之間間隔的時間
複製程式碼

2. Pipiline

HTTP 1.1 協議 中就把 Connection 的預設值改成了Keep-Alive,這樣同一個域名下的多個 HTTP 請求就可以複用同一個 TCP 連線
複製程式碼

3. 隊頭阻塞(Head of line blocking,下文簡稱 HOC)

序列請求執行時,如果第一個請求不執行完,後續的請求也無法執行
複製程式碼

4. SPDY

基於TCP實現,採用多路複用技術
SPDY 為各個資料包做好標記,指明他們屬於哪個 HTTP 請求,至於這些包能不能到達客戶端,SPDY 並不關心,因為資料可達性由 TCP 協議保證。既然客戶端一定能收到包,那就只要排序、拼接就行了。
複製程式碼

5. 多路複用(Multiplexing)

允許多個 HTTP 請求共享同一個 TCP 連線. 這麼做的代價是資料會略微有一些冗餘,每一個資源的資料包都要帶上標記,用來指明自己屬於哪個資源,這樣客戶端最後才能把他們正確的拼接起來
複製程式碼

6. TCP 視窗

只要你還在用 TCP 連結,HOC就是逃不掉的噩夢,TCP。協議會保證資料的可達性,如果發生了丟包或者錯包,資料就會被重傳,會有重傳就會有HOC問題。於是有了滑動視窗的概念。
eg:
如果TCP 視窗大小是 4,所以相當於一次傳送4個包,4個包中只要有1個返回(文章裡面說的是隻要第四個包的ACK返回了,我理解的是其中一個返回就行),就可以確信是另三個 ACK 丟了而不是資料包丟了。因此傳送方可以大膽的把視窗向後滑動四位。
複製程式碼

7. QUIC

基於 UDP 實現,由於UDP協議和TCP協議不同,只負責傳送資料,並不保證資料可達性。所以QUIC 協議需要自己保證資料可達性。
複製程式碼

8. 前向恢復(FEC: Fowrard Error Correcting):

利用已有資料就能進行錯誤恢復的技術
使用異或: a ^ a = 0     a ^ 0 = a
	
假設初始狀態:
A1 ^ A2 ^ A3 ^ ... ^ An = T

(A1 ^ A1) ^ A2 ^ A3 ^ ... ^ An = T ^ A1 

A2 ^ A3 ^ ... ^ An = T ^ A1

A3 ^ ... ^ An = T ^ A1 ^ A2

Ai = T ^ A1 ^ A2 ^ ... Ai-1 ^ Ai+1 ^ Ai+2 ^ ... ^ An
假設有5個資料包要傳送,我可以額外傳送一個包(上面例子中的T),它的值是前五個包的異或結果。這樣不管是前五個包中丟失了任何一個,或者某個包資料有錯(可以當成丟包來處理),都可以用另外四個包和這個冗餘的包T進行異或運算,從而恢復出來。
當然要注意的是,這種方案僅僅在只發生一個錯包或丟包時有效,如果丟失兩個包就無能為力了(這也就是為什麼只發一個冗餘包就夠的原因)。因此資料包和冗餘包之間的比值需要精心設計,如果比值過高,很容易出現丟兩個包的情況,如果比值過低,又會導致冗餘度太高,需要設計者根據概率計算結果進行權衡。
複製程式碼

相關文章