HTTPS工作原理
爲什麽需要 HTTPS?
我們爲什麽需要 HTTPS?主要有如下三個原因:
HTTPS 是什麽?SSL/TLS 是什麽?
于是 IETF 将 SSL 作了标準化,重新命名爲 TLS(Transport Layer Security)。在 1999 年,TLS 1.0 誕生了(其實也就是 SSL 3.1)。
SSL/TLS 發展史
SSL/TLS 發展史如上圖:
-
Google 将在 Chrome 72 中不推薦使用 TLS 1.0 和 1.1,而 Chrome 81 之後将會完全不支持。
-
Mozilla 的 Firefox,微軟的 Edge 和 IE 以及蘋果的 Safari 都會分别于 2020 年逐漸移除對 TLS 1.0 和 1.1 的支持。
要關閉浏覽器對 TLS 1.0 和 1.1 的支持,可以在 Internet 選項中修改:
SSL/TLS 的工作原理
需要理解 SSL/TLS 的工作原理,我們需要掌握加密算法。
加密算法有兩種:
-
對稱加密
-
非對稱加密
先來看下整個 SSL/TLS 的握手過程,之後我們再分步驟詳細解讀,每一步都幹了些什麽。
①當 TCP 建立連接之後,TLS 握手的第一步由客戶端發起,發送 ClientHello 的消息到服務器。
-
客戶端支持的 SSL/TLS 版本
-
客戶端支持的加密套件(Cipher Suites)
-
會話 Idsession id(如果有的值的話,服務器端會複用對應的握手信息,避免短時間内重複握手)
-
随機數 client-random
延伸閱讀:
加密套件名如:“TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA256”,這麽長的名字看着有點暈吧,不用怕,其實它的命名非常規範,格式很固定。基本的形式是“密鑰交換算法-服務身份驗證算法-對稱加密算法-握手校驗算法”。
握手過程中,證書簽名使用的 RSA 算法,如果證書驗證正确,再使用 ECDHE 算法進行密鑰交換,握手後的通信使用的是 AES256 的對稱算法分組模式是 GCM。
驗證證書簽名合法性使用 SHA256 作哈希算法檢驗。相關的算法的用處将在後文中詳解。
②然後服務器端在收到這個 ClientHello,從中選擇服務器支持的版本和套件,發送 ServerHello 消息:
-
服務器所能支持的最高 SSL/TLS 版本
-
服務器選擇的加密套件
-
随機數 server-random
-
會話 Idsession id(用于下次複用當前握手的信息,避免短時間内重複握手。)
随後服務器發送服務器的安全證書(含公鑰)。如果需要客戶端也提供證書的話,還會發出客戶端證書請求(Client Certificate Request),隻有少數金融機構才需要客戶端也提供客戶端證書。
此後客戶端發送 Server Hello Done 消息表示 Hello 階段完成。
③客戶端收到 ServerHello 後,會對收到的證書進行驗證。
我們來看一下爲什麽可以通過 CA(Certificate Authority,證書頒發機構)簽發的證書來确認網站的身份?
當我們安裝操作系統或者浏覽器的時候,會安裝一組可信任的 CA(根證書 CA 包括 GlobalSign、GeoTrust、Verisign 等)列表。
根 CA 如 GlobalSign 就在我們的可信任的 CA 列表裏,你的浏覽器或者操作系統含有 GlobalSign 的公鑰。
浏覽器首先用哈希函數對明文信息的摘要做哈希得到一個哈希值(用到的就是證書中的簽名哈希算法 SHA256),然後用根 CA 的公鑰對根證書的簽名作解密得到另一個哈希值(用到的算法就是 RSA 非對稱算法)。
這樣就免受中間人攻擊了,因爲假如有中間人修改了證書的内容(如将證書中的公鑰替換成自己的公鑰),那麽将獲得不同的哈希值,從而兩個哈希值不匹配導緻驗證失敗。
如果要繞過這個機制,中間人必須要也替換簽名,使簽名也相匹配。而做到這一點就需要破解到了根證書的密鑰(而這是不可能的,中間人必然會失敗)。
那聰明的你肯定也想到了,如果你開發了一個系統還在測試階段,還沒有正式申請一張證書,那麽你可以爲服務器自簽名一張證書,然後将證書導入客戶端的 CA 信任列表中。
可以看到證書路徑是:
-
GlobalSign Root CA-R2→GTS CA 1O1→*.google.com
因爲我們的浏覽器信任 GlobalSign Root CA,根據信任鏈機制,你相信了根 CA 頒發的證書,也要相信它簽名的子 CA 頒發的證書,也要相信子 CA 簽名的子子 CA 的證書。
而我們通過一級級的校驗,如果從根證書到最下層的證書都沒有被篡改過,我們就相信最下層的這個服務器證書是合法的。所以在這個機制中,你就需要無條件的相信根證書的頒發機構。
如果通過驗證,客戶端生成一個随機數 pre-master,用于密鑰交換過程。
④密鑰交換過程:客戶端用第三步中服務器的證書中拿到服務器的公鑰,用這個公鑰加密(算法是加密套件中的密鑰交換算法,譬如 ECDHE 算法)生成密文發送給服務器。
⑤客戶端用 server-random+client-random+pre-master 一起計算出對稱密鑰 master secret。
⑥服務器收到第四步的信息之後,用服務器的私鑰對密文進行解密得到密鑰 pre-master。
因爲隻有服務器有私鑰,可以針對客戶端發出的加密過的信息進行解密得到 pre-master,這樣就保證了隻有服務器和客戶端知道 pre-master。
服務器端也可以用 server-random+client-random+pre-master 一起計算出對稱密鑰 master secret。
現在客戶端和服務器均有密鑰 master secret 了,後面就可以用它來進行加密和解密了。
爲什麽不能隻用一個 pre-master 作爲之後加密的對稱密鑰?
⑦客戶端用 master secret 加密了一條握手完成的消息發送給服務器。
⑧服務器端也回發了一條用 master secret 加密的握手完成的消息。
⑨當兩方都收到對方發送的握手消息之後,也成功解密後,就可以用 master secret 愉快的開始數據加密和解密了。
綜上,整個握手過程主要是通過一系列步驟通過非對稱加密的算法交換得到了 master secret,這個步驟通常需要幾百毫秒,但是就是這一頓猛操作之後使得隻有服務器和客戶端知道 master secret。
之後的通信又利用了高效的對稱算法對所有信息進行加密和解密,雖然加密和解密也需要耗時耗流量,不過信息是完全不可能被别人篡改和破解的,這一點損耗還是值得的。