1. 程式人生 > >SSL協議握手詳解

SSL協議握手詳解

本週,CloudFlare宣佈,開始提供Keyless服務,即你把網站放到它們的CDN上,不用提供自己的私鑰,也能使用SSL加密連結。

CloudFlare

我看了CloudFlare的說明(這裡這裡),突然意識到這是絕好的例子,可以用來說明SSL/TLS協議的執行機制。它配有插圖,很容易看懂。

下面,我就用這些圖片作為例子,配合我半年前寫的《SSL/TLS協議執行機制的概述》,來解釋SSL協議。

一、SSL協議的握手過程

開始加密通訊之前,客戶端和伺服器首先必須建立連線和交換引數,這個過程叫做握手(handshake)。

假定客戶端叫做愛麗絲,伺服器叫做鮑勃,整個握手過程可以用下圖說明(點選看大圖)。

握手階段分成五步。

第一步,愛麗絲給出協議版本號、一個客戶端生成的隨機數(Client random),以及客戶端支援的加密方法。

第二步,鮑勃確認雙方使用的加密方法,並給出數字證書、以及一個伺服器生成的隨機數(Server random)。

第三步,愛麗絲確認數字證書有效,然後生成一個新的隨機數(Premaster secret),並使用數字證書中的公鑰,加密這個隨機數,發給鮑勃。

第四步,鮑勃使用自己的私鑰,獲取愛麗絲髮來的隨機數(即Premaster secret)。

第五步,愛麗絲和鮑勃根據約定的加密方法,使用前面的三個隨機數,生成"對話金鑰"(session key),用來加密接下來的整個對話過程。

上面的五步,畫成一張圖,就是下面這樣。

二、私鑰的作用

握手階段有三點需要注意。

(1)生成對話金鑰一共需要三個隨機數。

(2)握手之後的對話使用"對話金鑰"加密(對稱加密),伺服器的公鑰和私鑰只用於加密和解密"對話金鑰"(非對稱加密),無其他作用。

(3)伺服器公鑰放在伺服器的數字證書之中。

從上面第二點可知,整個對話過程中(握手階段和其後的對話),伺服器的公鑰和私鑰只需要用到一次。這就是CloudFlare能夠提供Keyless服務的根本原因。

某些客戶(比如銀行)想要使用外部CDN,加快自家網站的訪問速度,但是出於安全考慮,不能把私鑰交給CDN服務商。這時,完全可以把私鑰留在自家伺服器,只用來解密對話金鑰,其他步驟都讓CDN服務商去完成。

上圖中,銀行的伺服器只參與第四步,後面的對話都不再會用到私鑰了。

三、DH演算法的握手階段

整個握手階段都不加密(也沒法加密),都是明文的。因此,如果有人竊聽通訊,他可以知道雙方選擇的加密方法,以及三個隨機數中的兩個。整個通話的安全,只取決於第三個隨機數(Premaster secret)能不能被破解。

雖然理論上,只要伺服器的公鑰足夠長(比如2048位),那麼Premaster secret可以保證不被破解。但是為了足夠安全,我們可以考慮把握手階段的演算法從預設的RSA演算法,改為 Diffie-Hellman演算法(簡稱DH演算法)。

採用DH演算法後,Premaster secret不需要傳遞,雙方只要交換各自的引數,就可以算出這個隨機數。

上圖中,第三步和第四步由傳遞Premaster secret變成了傳遞DH演算法所需的引數,然後雙方各自算出Premaster secret。這樣就提高了安全性。

四、session的恢復

握手階段用來建立SSL連線。如果出於某種原因,對話中斷,就需要重新握手。

這時有兩種方法可以恢復原來的session:一種叫做session ID,另一種叫做session ticket。

session ID的思想很簡單,就是每一次對話都有一個編號(session ID)。如果對話中斷,下次重連的時候,只要客戶端給出這個編號,且伺服器有這個編號的記錄,雙方就可以重新使用已有的"對話金鑰",而不必重新生成一把。

上圖中,客戶端給出session ID,伺服器確認該編號存在,雙方就不再進行握手階段剩餘的步驟,而直接用已有的對話金鑰進行加密通訊。

session ID是目前所有瀏覽器都支援的方法,但是它的缺點在於session ID往往只保留在一臺伺服器上。所以,如果客戶端的請求發到另一臺伺服器,就無法恢復對話。session ticket就是為了解決這個問題而誕生的,目前只有Firefox和Chrome瀏覽器支援。

上圖中,客戶端不再發送session ID,而是傳送一個伺服器在上一次對話中傳送過來的session ticket。這個session ticket是加密的,只有伺服器才能解密,其中包括本次對話的主要資訊,比如對話金鑰和加密方法。當伺服器收到session ticket以後,解密後就不必重新生成對話金鑰了。