摘自人類身份驗證 - SegmentFault

1. SSL/TLS概覽

SSL是一個介於HTTP協議與TCP之間的一個可選層,其位置大致如下:

2. 密鑰協商過程——TLS握手

SSL協議分為兩部分:Handshake Protocol和Record Protocol。其中Handshake Protocol用來協商密鑰,協議的大部分內容就是通信雙方如何利用它來安全的協商出一份密鑰。 Record Protocol則定義了傳輸的格式。

由於非對稱加密的速度比較慢,所以它一般用於密鑰交換,雙方通過公鑰演算法協商出一份密鑰,然後通過對稱加密來通信,當然,為了保證數據的完整性,在加密前要先經過HMAC的處理。

SSL預設只進行server端的認證,客戶端的認證是可選的。以下是其流程圖(摘自TLS協議)。

2.1 客戶端發出請求(ClientHello)

由於客戶端(如瀏覽器)對一些加解密演算法的支持程度不一樣,但是在TLS協議傳輸過程中必須使用同一套加解密演算法才能保證數據能夠正常的加解密。在TLS握手階段,客戶端首先要告知服務端,自己支持哪些加密演算法,所以客戶端需要將本地支持的加密套件(Cipher Suite)的列表傳送給服務端。除此之外,客戶端還要產生一個隨機數,這個隨機數一方面需要在客戶端保存,另一方面需要傳送給服務端,客戶端的隨機數需要跟服務端產生的隨機數結合起來產生後面要講到的 Master Secret 。

綜上,在這一步,客戶端主要向伺服器提供以下信息:

  1. 支持的協議版本,比如TLS 1.0版
  2. 一個客戶端生成的隨機數,稍後用於生成"對話密鑰"
  3. 支持的加密方法,比如RSA公鑰加密
  4. 支持的壓縮方法

2.2 伺服器回應(SeverHello)

上圖中,從Server Hello到Server Done,有些服務端的實現是每條單獨發送,有服務端實現是合併到一起發送。Sever Hello和Server Done都是隻有頭沒有內容的數據。

服務端在接收到客戶端的Client Hello之後,服務端需要將自己的證書發送給客戶端。這個證書是對於服務端的一種認證。

此外,對於非常重要的保密數據,服務端還需要對客戶端進行驗證,以保證數據傳送給了安全的合法的客戶端。服務端可以向客戶端發出 Cerficate Request 消息,要求客戶端發送證書對客戶端的合法性進行驗證。

跟客戶端一樣,服務端也需要產生一個隨機數發送給客戶端。客戶端和服務端都需要使用這兩個隨機數來產生Master Secret。

最後服務端會發送一個Server Hello Done消息給客戶端,表示Server Hello消息結束了。

綜上,在這一步,伺服器的回應包含以下內容:

  1. 確認使用的加密通信協議版本,比如TLS 1.0版本。如果瀏覽器與伺服器支持的版本不一致,伺服器關閉加密通信
  2. 一個伺服器生成的隨機數,稍後用於生成"對話密鑰"
  3. 確認使用的加密方法,比如RSA公鑰加密
  4. 伺服器證書

2.3 客戶端回應(Certificate Verify)

Client Key Exchange

如果服務端需要對客戶端進行驗證,在客戶端收到服務端的 Server Hello 消息之後,首先需要向服務端發送客戶端的證書,讓服務端來驗證客戶端的合法性。

Certificate Verify

接著,客戶端需要對服務端的證書進行檢查,如果證書不是可信機構頒布、或者證書中的域名與實際域名不一致、或者證書已經過期,就會向訪問者顯示一個警告,由其選擇是否還要繼續通信。如果證書沒有問題,客戶端就會從伺服器證書中取出伺服器的公鑰。然後,向伺服器發送下面三項信息:

  1. 一個隨機數。該隨機數用伺服器公鑰加密,防止被竊聽
  2. 編碼改變通知,表示隨後的信息都將用雙方商定的加密方法和密鑰發送
  3. 客戶端握手結束通知,表示客戶端的握手階段已經結束。這一項同時也是前面發送的所有內容的hash值,用來供伺服器校驗

上面第一項的隨機數,是整個握手階段出現的第三個隨機數,它是客戶端使用一些加密演算法(例如:RSA, Diffie-Hellman)產生一個48個位元組的Key,這個Key叫 PreMaster Secret,很多材料上也被稱作 PreMaster Key。

ChangeCipherSpec

ChangeCipherSpec是一個獨立的協議,體現在數據包中就是一個位元組的數據,用於告知服務端,客戶端已經切換到之前協商好的加密套件(Cipher Suite)的狀態,準備使用之前協商好的加密套件加密數據並傳輸了。

在ChangecipherSpec傳輸完畢之後,客戶端會使用之前協商好的加密套件和Session Secret加密一段 Finish 的數據傳送給服務端,此數據是為了在正式傳輸應用數據之前對剛剛握手建立起來的加解密通道進行驗證。

2.4 伺服器的最後回應(Server Finish)

服務端在接收到客戶端傳過來的 PreMaster 加密數據之後,使用私鑰對這段加密數據進行解密,並對數據進行驗證,也會使用跟客戶端同樣的方式生成 Session Secret,一切準備好之後,會給客戶端發送一個 ChangeCipherSpec,告知客戶端已經切換到協商過的加密套件狀態,準備使用加密套件和 Session Secret加密數據了。之後,服務端也會使用 Session Secret 加密一段 Finish 消息發送給客戶端,以驗證之前通過握手建立起來的加解密通道是否成功。

根據之前的握手信息,如果客戶端和服務端都能對Finish信息進行正常加解密且消息正確的被驗證,則說明握手通道已經建立成功,接下來,雙方可以使用上面產生的Session Secret對數據進行加密傳輸了。

2.5 幾個secret

PreMaster secret

PreMaster Secret是在客戶端使用RSA或者Diffie-Hellman等加密演算法生成的。它將用來跟服務端和客戶端在Hello階段產生的隨機數結合在一起生成 Master Secret。在客戶端使用服務端的公鑰對PreMaster Secret進行加密之後傳送給服務端,服務端將使用私鑰進行解密得到PreMaster secret。也就是說服務端和客戶端都有一份相同的PreMaster secret和隨機數。

PreMaster secret前兩個位元組是TLS的版本號,這是一個比較重要的用來核對握手數據的版本號,因為在Client Hello階段,客戶端會發送一份加密套件列表和當前支持的SSL/TLS的版本號給服務端,而且是使用明文傳送的,如果握手的數據包被破解之後,攻擊者很有可能串改數據包,選擇一個安全性較低的加密套件和版本給服務端,從而對數據進行破解。所以,服務端需要對密文中解密出來對的PreMaster版本號跟之前Client Hello階段的版本號進行對比,如果版本號變低,則說明被串改,則立即停止發送任何消息。

Master secret

上面已經提到,由於服務端和客戶端都有一份相同的PreMaster secret和隨機數,這個隨機數將作為後面產生Master secret的種子,結合PreMaster secret,客戶端和服務端將計算出同樣的Master secret。

Master secret是有系列的hash值組成的,它將作為數據加解密相關的secret的 Key Material 的一部分。Key Material最終解析出來的數據如下:

其中,write MAC key,就是session secret或者說是session key。Client write MAC key是客戶端發數據的session secret,Server write MAC secret是服務端發送數據的session key。MAC(Message Authentication Code),是一個數字簽名,用來驗證數據的完整性,可以檢測到數據是否被串改。

2.6 應用數據傳輸

在所有的握手階段都完成之後,就可以開始傳送應用數據了。應用數據在傳輸之前,首先要附加上MAC secret,然後再對這個數據包使用write encryption key進行加密。在服務端收到密文之後,使用Client write encryption key進行解密,客戶端收到服務端的數據之後使用Server write encryption key進行解密,然後使用各自的write MAC key對數據的完整性包括是否被串改進行驗證。


推薦閱讀:
相關文章