前言
本文將逐步的來還原 HTTPS 的設計過程,理解從 HTTP 到 HTTPS 的轉變中,到底都發生了些什麼。
HTTP 的缺陷
首先先來說說為什麼需要 HTTPS, 也就是 HTTP 的主要不足是什麼
- 通訊使用明文(不加密),內容可能會被竊聽
- 不驗證通訊方的身份,因此有可能遭遇偽裝
- 無法證明報文的完整性,所以有可能已遭篡改
通訊使用明文可能被竊聽
HTTP 本身不具備加密的功能,即 HTTP 報文使用明文(指未經過加密的報文)方式傳送。
所謂網際網路,是由能連通到全世界的網路組成的。無論世界哪個角落的伺服器在和客戶端通訊時,在此通訊線路上的某些網路裝置、光纜、計算機等都不可能是個人的私有物,所以不排除某個環節中會遭到惡意窺視行為。
比如使用免費的抓包工具 Wireshark, 就可以獲取 HTTP 的請求和響應報文進行分析。
加密處理防止被竊聽
目前大家正在研究的如何防止竊聽保護資訊的幾種對策中,最為普及的就是加密技術。加密的物件為以下
通訊加密
HTTP 協議中沒有加密機制,但可以通過和 SSL(Secure Socket Layer,安全套接層)或 TLS(Transport Layer Security,安全層傳輸協議)的組合使用,加密 HTTP 的通訊內容
通常,HTTP 直接和 TCP 通訊。當使用 SSL 時,則演變成先和 SSL 通訊,再由 SSL 和 TCP 通訊了。用 SSL 建立安全通訊線路之後,就可以在這條線路上進行 HTTP 通訊了。
SSL 是獨立於 HTTP 的協議,所以不光是 HTTP 協議,其他執行在應用層的 SMTP 和 Telnet 等協議均可配合 SSL 協議使用。可以說 SSL 是當今世界上應用最為廣泛的網路安全技術。
內容的加密
由於 HTTP 協議中沒有加密機制,那麼就對 HTTP 協議傳輸的內容本身加密。即把 HTTP 報文裡所含的內容進行加密處理。
在這種情況下,客戶端需要對 HTTP 報文進行加密處理後再傳送請求。
為了做到有效的內容加密,前提是要求客戶端和伺服器同時具備加密和解密機制。
不驗證通訊方的身份就可能遭遇偽裝
在 HTTP 協議通訊時,由於不存在確認通訊方的處理步驟,任何人都可以發起請求。另外,伺服器只要接收到請求,不管對方是誰都會返回一個響應 (但也僅限於傳送端的 IP 地址和埠號沒有被 Web 伺服器設定限制訪問的前提下)
HTTP 協議的實現本身非常簡單,不論是誰傳送過來的請求都會返回響應,因此不確認通訊方,會存在以下各種隱患
- 無法確定請求傳送至目標的 Web 伺服器是否是按真實意圖返回響應的那臺伺服器。有可能是偽裝的 Web 伺服器
- 無法確定響應返回到的客戶端是否是按真實意圖接收響應的那個客戶端。有可能是偽裝的客戶端
- 無法確定正在通訊的對方是否具備訪問許可權。因為某些 Web 伺服器上儲存著重要的資訊,只想發給特定使用者通訊的許可權
- 即使是無意義的請求也會照單全收。無法阻止海量請求下的 DoS 攻擊 (Denial of Service,拒絕服務攻擊)
使用證書驗證身份
雖然使用 HTTP 協議無法確定通訊方,但如果使用 SSL 則可以。SSL 不僅提供加密處理,而且還使用了一種被稱為證書的手段,可用於確定雙方身份
證書由值得信任的第三方機構頒發,用以證明伺服器和客戶端是實際存在的。另外,偽造證書從技術角度來說是異常困難的一件事。所以只要能夠確認通訊方(伺服器或客戶端)持有的證書,即可判斷通訊方的真實意圖
通過使用證書,以證明通訊方就是意料中的伺服器。這對使用者個人來講,也減少了個人資訊洩露的危險性。
另外,客戶端持有證書即可完成個人身份的確認,也可用於對 Web 網站的認證環節。
古往今來,三角戀的關係一直都不被看好,但是在 HTTPS 的協議裡,客戶端,伺服器和被信賴的第三方機構這三者的關係卻是奠定一切的基礎。
無法證明報文完整性,可能已遭篡改
所謂完整性是指資訊的準確度。若無法證明其完整性,通常也就意味著無法判斷資訊是否準確
由於 HTTP 協議無法證明通訊的報文完整性,因此在請求或響應送 出之後直到對方接收之前的這段時間內,即使請求或響應的內容遭到篡改,也沒有辦法獲悉。
比如,從某個 Web 網站上下載內容,是無法確定客戶端下載的檔案和伺服器上存放的檔案是否前後一致的。檔案內容在傳輸途中可能已經被篡改為其他的內容。即使內容真的已改變,作為接收方的客戶端也是覺察不到的。
像這樣,請求或響應在傳輸途中,遭攻擊者攔截並篡改內容的攻擊稱為中間人攻擊(Man-in-the-Middle attack,MITM)。
雖然 HTTP 協議中有確定報文完整性的方法,但事實上並不便捷、可靠。其中常用的是 MD5 和 SHA-1 等雜湊值校驗的方法,以及用來確認檔案的數 字簽名方法。
可惜的是,用這些方法也依然無法百分百保證確認結果正確。因 MD5 本身被改寫的話,使用者是沒有辦法意識到的。
為了有效防止這些弊端,有必要使用 HTTPS。SSL 提供認證和加密處理及摘要功能。僅靠 HTTP 確保完整性是非常困難的,因此通過和其他協議組合使用來實現這個目標。
HTTP+ 加密 + 認證 + 完整性保護 = HTTPS
HTTPS 並非是應用層的一種新協議。只是 HTTP 通訊介面部分用 SSL(Secure Socket Layer)和 TLS(Transport Layer Security)協議代替而已。
簡言之,所謂 HTTPS,其實就是身披 SSL 協議這層外殼的 HTTP
加密方法
在對 SSL 進行講解之前,我們先來了解一下加密方法。
加密方法只是解決方案,我們首先要做的是理解我們的問題域——什麼是安全?
A 與 B 通訊的內容,有且只有 A 和 B 有能力看到通訊的真正內容
好,問題域已經定義好了(現實中當然不止這一種定義)。對於解決方案,很容易就想到了對訊息進行加密。
共享金鑰方式加密(對稱金鑰加密)
加密和解密同用一個金鑰的方式稱為共享金鑰加密(Common key crypto system),也被叫做對稱金鑰加密。
只要這個金鑰不公開給第三者,同時金鑰足夠安全,我們就解決了我們一開始所定問題域了。因為世界上有且只有圖上的客戶端與伺服器知道如何加密和解密他們之間的訊息。
但是在實際的網際網路環境下 Web 伺服器的通訊模型沒有這麼簡單,因為如果伺服器端對所有的客戶端通訊都使用同樣的對稱加密演算法,無異於沒有加密。所以實際中 Web 伺服器與每個客戶端使用不同的對稱加密演算法
以共享金鑰方式加密(對稱金鑰加密)時必須將金鑰也發給對方。那麼就會產生一個新的問題,究竟怎樣才能安全地轉交?
在網際網路上轉發金鑰時,如果通訊被監聽那麼金鑰就可會落入攻擊者之 手,同時也就失去了加密的意義。另外還得設法安全地保管接收到的金鑰。
傳送金鑰就有被竊聽的風險,但不傳送,對方就不能解密。再說,金鑰若能夠安全傳送,那資料也應該能安全送達
公開金鑰加密(非對稱加密)
密碼學領域中,有一種稱為“非對稱加密”的加密演算法,特點是私鑰加密後的密文,只要是公鑰,都可以解密,但是公鑰加密後的密文,只有私鑰可以解密。私鑰只有一個人有,而公鑰可以發給所有的人。
使用公開金鑰加密方式,傳送密文的一方使用對方的公開金鑰進行加密處理,對方收到被加密的資訊後,再使用自己的私有金鑰進行解密。利用這種方式,不需要傳送用來解密的私有金鑰,也不必擔心金鑰被攻擊者竊聽而盜走。
另外,要想根據密文和公開金鑰,恢復到資訊原文是異常困難的,因為解密過程就是在對離散對數進行求值,這並非輕而易舉就能辦到。退一步講,如果能對一個非常大的整數做到快速地因式分解,那麼密碼破解還是存在希望的。但就目前的技術來看是不太現實的。
HTTPS 加密機制
若金鑰能夠實現安全交換,那麼有可能會考慮僅使用公開金鑰加密來通訊。但是公開金鑰加密與共享金鑰加密相比,其處理速度要慢。
所以應充分利用兩者各自的優勢,將多種方法組合起來用於通訊。在交換金鑰環節使用公開金鑰加密方式,之後的建立通訊交換報文階段則使用共享密 鑰加密方式。
HTTPS 採用共享金鑰加密和公開金鑰加密兩者並用的混合加密機制
公開金鑰加密處理起來比共享金鑰加密方式更為複雜,因此若在通訊時使用公開金鑰加密方式,效率就很低
證明公開金鑰正確性的證書
細心的人可能已經注意到瞭如果使用公開金鑰加密,客戶端必須需要一開始就持有公鑰,要不沒法開展加密行為啊,所以需要伺服器端將公鑰傳送給每一個客戶端。
遺憾的是,公開金鑰加密方式還是存在一些問題的。那就是無法證明公開金鑰本身就是貨真價實的公開金鑰。比如,正準備和某臺伺服器建立公開金鑰加密方式下的通訊時,如何證明收到的公開金鑰就是原本預想的那臺伺服器發行的公開金鑰。既如果伺服器端傳送公鑰給客戶端時,被中間人調包了,怎麼辦?
為了解決上述問題,可以使用由數字證書認證機構(CA,Certificate Authority)和其相關機關頒發的公開金鑰證書。
數字證書認證機構處於客戶端與伺服器雙方都可信賴的第三方機構的立場上。伺服器會將這份由數字證書認證機構頒發的公鑰證書傳送給客戶端,以進行公開金鑰加密方式通訊。公鑰證書也可叫做數字證書或直接稱為證書。
接到證書的客戶端可使用數字證書認證機構的公開金鑰,對那張證書上的數字簽名進行驗證,一旦驗證通過,客戶端便可明確兩件事:
- 認證伺服器的公開金鑰的是真實有效的數字證書認證機構
- 伺服器的公開金鑰是值得信賴的
此處認證機關的公開金鑰必須安全地轉交給客戶端。使用通訊方式時,如何安全轉交是一件很困難的事,因此,多數瀏覽器開發商釋出版本時,會事先在內部植入常用認證機關的公開金鑰
到這裡可能會感覺 HTTPS 的通訊過程結束了,但是還遺漏了一個場景:
第三方機構不可能只給你一家公司製作證書,它也可能會給中間人這樣有壞心思的公司發放證書。這樣的,中間人就有機會對你的證書進行調包,客戶端在這種情況下是無法分辨出是接收的是你的證書,還是中間人的。因為不論中間人,還是你的證書,都能使用第三方機構的公鑰進行解密。如圖
那客戶端是如何來驗證證書的呢? 答案是證書本身就已經告訴客戶端怎麼驗證證書的真偽。
證書上寫著如何根據證書的內容生成證書編號。客戶端拿到證書後根據證書上的方法自己生成一個證書編號,如果生成的證書編號與證書上的證書編號相同,那麼說明這個證書是真實的。
同時,為避免證書編號本身又被調包,所以使用第三方的私鑰進行加密。
證書的製作如圖所示
當客戶端拿到證書後,開始對證書中的內容進行驗證,如果客戶端計算出來的證書編號與證書中的證書編號相同,則驗證通過:
以上即為 HTTPS 通訊的全部過程
思路整理
為了更好地理解 HTTPS,我們來整理一下 HTTPS 的通訊步驟
- 客戶端通過傳送 Client Hello 報文開始 SSL 通訊。報文中包含客戶端支援的 SSL 的指定版本、加密元件(Cipher Suite)列表(所使用的加密演算法及金鑰長度等)
- 伺服器可進行 SSL 通訊時,會以 Server Hello 報文作為應答。和客戶端一樣,在報文中包含 SSL 版本以及加密元件。伺服器的加密元件內容是從接收 到的客戶端加密元件內篩選出來的。
- 之後伺服器傳送 Certificate 報文。報文中包含公開金鑰證書。
- 最後伺服器傳送 Server Hello Done 報文通知客戶端,最初階段的 SSL 握手協商部分結束。
- SSL 第一次握手結束之後,客戶端以 Client Key Exchange 報文作為迴應。報文中包含通訊加密中使用的一種被稱為 Pre-master secret 的隨機密碼串。該 報文已用步驟 3 中的公開金鑰進行加密。
- 接著客戶端繼續傳送 Change Cipher Spec 報文。該報文會提示伺服器,在此報文之後的通訊會採用 Pre-master secret 金鑰加密。
- 客戶端傳送 Finished 報文。該報文包含連線至今全部報文的整體校驗值。這次握手協商是否能夠成功,要以伺服器是否能夠正確解密該報文作為判定標準。
- 伺服器同樣傳送 Change Cipher Spec 報文。
- 伺服器同樣傳送 Finished 報文。
- 伺服器和客戶端的 Finished 報文交換完畢之後,SSL 連線就算建立完成。當然,通訊會受到 SSL 的保護。從此處開始進行應用層協議的通訊,即發 送 HTTP 請求。
- 應用層協議通訊,即傳送 HTTP 響應。
- 最後由客戶端斷開連線。斷開連線時,傳送 close_notify 報文。
以上做了一些省略,這步之後再傳送 TCP FIN 報文來關閉與 TCP 的通訊。
在以上流程中,應用層傳送資料時會附加一種叫做 MAC(Message Authentication Code)的報文摘要。MAC 能夠查知報文是否遭到篡改,從而保護報文的完整性。
HTTPS 缺陷
HTTPS 也存在一些問題,那就是當使用 SSL 時,它的處理速度會變慢。
由於 HTTPS 還需要做伺服器、客戶端雙方加密及解密處理,因此會消耗 CPU 和記憶體等硬體的資源
和 HTTP 通訊相比,SSL 通訊部分消耗網路資源。而 SSL 通訊部分,又因為要對通訊進行處理,所以時間上又延長了
相關技術文章推薦
想了解如何給自己的網站啟用 HTTPS 可以參考左耳朵耗子的如何免費的讓網站啟用HTTPS
Android HTTPS 相關的可以參考鴻洋的Android HTTPS 相關完全解析 當 OKHttp 遇到 Https
參考