阮一峰:圖解SSL/TLS協議

jopen 10年前發布 | 94K 次閱讀 SSL 安全相關

作者:  阮一峰

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

阮一峰:圖解SSL/TLS協議

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

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

        一、SSL 協議的握手過程

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

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

阮一峰:圖解SSL/TLS協議

        握手階段分成五步。

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

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

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

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

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

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

阮一峰:圖解SSL/TLS協議

        二、私鑰的作用

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

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

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

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

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

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

阮一峰:圖解SSL/TLS協議

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

        三、DH 算法的握手階段

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

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

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

阮一峰:圖解SSL/TLS協議

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

        四、session 的恢復

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

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

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

阮一峰:圖解SSL/TLS協議

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

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

阮一峰:圖解SSL/TLS協議

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

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!