很多人一提到 HTTPS,第一反應就是安全,對於普通用戶來說這就足夠了,對於程序員來說,有必要了解下 HTTP 到底有什麼問題?HTTPS 是如何解決的?其背後的解決思路和方法是什麼?下面坐下簡單的描述,HTTPS 體系非常複雜,自己無法做到很詳細和精準的分析。

性能

HTTP 有典型的幾個問題,第一就是性能,HTTP 是基於 TCP 的,所以網絡層就不說了(快慢不是 HTTP 的問題)。比較嚴重的問題在於 HTTP 頭是不能壓縮的,每次要傳遞很大的數據包。另外 HTTP 的請求模型是每個連接只能支持一個請求,所以會顯得很慢。

那麼 HTTPS 是解決這些問題的嗎?不是,實際上 HTTPS 是在 HTTP 協議上又加了一層,會更慢,相信未來會逐步解決的。同時 HTTPS 用到了很多加密算法,這些算法的執行也是會影響速度的。

為什麼說 HTTPS 提升了性能呢,因為只有支持了 HTTPS,才能部署 HTTP/2,而 HTTP/2 協議會提升速度,能夠有效減輕客戶端和服務器端的壓力,讓響應更快速,HTTP/2 未來會寫一篇文章說說,這裏只要知道一點:HTTP/2 能夠加快速度的主要原因在於多路復用,同一個連接能夠并行發送和接收多個請求。

安全性

當用戶在瀏覽器輸入一個網址的時候,在地址欄上看到小鎖圖標,就會安心,潛意識的認為自己的上網行為是安全的,當然對於小白用戶來說可能還不明白,但是未來會慢慢改善的(萬事開頭難嗎)。

那麼 HTTP 到底有什麼安全問題呢,看幾個例子:

(1)由於互聯網傳輸是能夠被攔截的,所以假如你的上網方式被別人控制了(沒有絕對的安全),那麼你的任何行為和信息攻擊者都會知道,比如我們連上一個匿名的 WIFI,當你上網的時候,輸入的網站密碼可能就已經泄漏了。

(2)當我們在上一個網站的時候,莫名其妙跳出一個廣告(這個廣告並不是這個網站的),那是因為訪問的頁面可能被運營商強制修改了(加入了他自己的內容,比如廣告)。

HTTP 最大的問題就在於數據沒有加密,以及通信雙方沒有辦法進行身份驗證( confidentiality and authentication),由於數據沒有加密,那麼只要數據包被攻擊者劫持,信息就泄漏了。身份驗證的意思就是服務器並不知道連接它的客戶端到底是誰,而客戶端也不確定他連接的服務器就是他想連接的服務器,雙方之間沒有辦法進行身份確認。

HTTPS 背後的密碼學

為了解決 HTTP 的兩個核心問題,HTTPS 出現了,HTTPS 包含了核心的幾個部分,TLS 協議、OpenSSL,證書。什麼是 OpenSSL 呢,它實現了世界上非常重要和多的密碼算法,而密碼學是解決問題最重要的一個環節。TLS 最重要的是握手的處理方式。證書的體系也很大,但是他們背後都是基於同樣的密碼學。

(1)既然 HTTP 沒有數據加密,那麼我們就加密下,對稱加密算法上場了,這種算法加密和解密要使用同一個密鑰,通信雙方需要知道這個密鑰(或者每次協商一個),實際上這種方法不太可能,這涉及到密鑰保密和配送的問題,一旦被攻擊者知道了密鑰,那麼傳輸的數據等同沒有加密。

(2)這個時候非對稱加密算法上場了,公鑰和私鑰是分開的,客戶端保存公鑰,服務器保存私鑰(不會公開),這時候好像能夠完美解決問題了。但實際上會存在兩個問題,第一就是非對稱加密算法運算很慢,第二就是會遇到中間人攻擊問題。先說說中間人攻擊的問題,假如使用非對稱加密算法,對於客戶端來說它拿到的公鑰可能並不是真正服務器的公鑰,因為客戶端上網的時候可能不會仔細分辨某個公鑰是和某個公司綁定的,假如錯誤的拿到攻擊者的公鑰,那麼他發送出去的數據包被劫持后,攻擊者用自己的私鑰就能反解了。

(5)接下來如何解決公鑰認證的問題呢?證書出現了,證書是由 CA 機構認證的,客戶端都充分信任它,它能夠證明你拿到的公鑰是特定機構的,然後就能使用非對稱加密算法加密了。證書是怎麼加密的呢?實際上也是通過非對稱加密算法,但是區別在於證書是用私鑰加密,公鑰解密。CA 機構會用自己的私鑰加密服務器用戶的公鑰,而客戶端則用 CA 機構的公鑰解出服務器的公鑰。聽上去有點暈,仔細體會下。

(6)上面說了非對稱加密算法加密解密非常耗時,對於 HTTP 這樣的大數據包,速度就更慢了,這時候可以使用對稱加密算法,這個密鑰是由客戶端和服務器端協商出來,並由服務器的公鑰進行加密傳遞,所以不存在安全問題。

(7)另外客戶端拿到證書後會驗證證書是否正確,它驗證的手段就是通過 Hash 摘要算法,CA 機構會將證書信息通過 Hash 算法運算后再用私鑰加密,客戶端用 CA 的公鑰解出后,再計算證書的 Hash 摘要值,兩者一致就說明驗證身份通過。

(8)HTTPS 解決的第三個問題是完整性問題,就是信息有沒有被篡改(信息能夠被反解),用的是 HMAC 算法,這個算法和 Hash 方法差不多,但是需要傳遞一個密鑰,這個密鑰就是客戶端和服務器端上面協商出來的。