眾所周知,HTTP 協議通過明文傳輸,是不安全的。於是,就在 HTTP 協議的基礎上,進行了資料加密,也就誕生了 HTTPS 協議。注意,HTTPS 並不是一個新的協議,它只不過是在 HTTP 的基礎上加了一層 TLS ( Transport Layer Security )
TLS是傳輸層加密協議,前身是SSL ( Secure Sockets Layer 翻譯為安全套接層)。由網景公司於1995年釋出。後改名為TLS
隨著公眾對資料安全性越來越重視,HTTPS 逐漸成為主流,現在還在使用 HTTP 的網站,在谷歌瀏覽器位址列前會有 “不安全” 字樣的提示。作為開發者,我們理應對 HTTPS 加密的原理有所瞭解。
HTTPS 的加密流程
概括來說,HTTPS 中的資料是通過對稱加密的方式來加密的,而對稱加密的金鑰是由客戶端生成的隨機字串來充當,再通過非對稱加密的方式加密後傳遞到服務端。接下來是詳細的流程。這裡,我們參考建立 tcp 連線中的三次握手的概念,在 https 加密過程中,服務端與客戶端也有三次握手
第一次握手(服務端傳送公鑰到客戶端)
服務端將公鑰以證書的形式傳送給客戶端,證書內包含伺服器端的公鑰,證書頒發機構,證書有效期,服務端域名等資訊。
第二次握手(客戶端對證書進行校驗並且向服務端傳送對稱金鑰)
客戶端收到證書後,會選擇是否信任證書,這裡是否信任可以根據域名,頒發機構,有效期等資訊來判斷,如果證書校驗不通過,就給予風險提示並斷開連線;如果校驗通過,就生成一個隨機數,用作對稱加密的金鑰,並取出證書中的公鑰,用該公鑰對隨機數進行加密,將加密後的結果傳送到服務端。
第三次握手(服務端用收到的對稱金鑰加密一段握手資訊,傳送到客戶端)
服務端收到客戶端發來的金鑰,先用自己的私鑰解密,解密成功後,用該對稱金鑰傳送一段握手資訊到客戶端。客戶端收到後,解密成功,至此,HTTPS 連線成功,後續的資料傳輸就會使用該對稱金鑰來進行加密。
以上就是 HTTPS 加密的大概的流程,接下來是一些細節上的問題。
HTTPS 是怎樣防止中間人攻擊的
我們知道,在第一次握手的過程中,中間人完全可以截獲服務端傳送給客戶端的公鑰,並且將自己的公鑰傳送給客戶端。客戶端用中間人的公鑰加密對稱金鑰,再將結果傳送給服務端,中間人再次截獲,用自己的私鑰解密,獲取金鑰,再用服務端的公鑰加密後傳送給服務端。這樣,中間人分別冒出服務端和客戶端跟彼此互動,就可以竊取資訊了。
解決方案
以上中間人攻擊成功的主要原因,是客戶端無法識別公鑰的來源是否來自真正的服務端。這裡的解決方案就是數字證書。
- 服務端通過向 CA 等被信任的機構申請獲取 CA 私鑰,並對服務端公鑰等資訊通過 hash 演算法生成訊息摘要,用 CA 私鑰對該訊息摘要加密,生成簽名,將該簽名封裝到證書中一起傳送到客戶端;
- 客戶端收到證書後,用 CA 公鑰對簽名進行解密,再對服務端公鑰等資訊生成訊息摘要,並將其與解密的結果進行比對,如果一致,就證明服務端的公鑰來源正確
這裡用到的 CA 私鑰是服務端向 CA 機構申請來的,而 CA 公鑰是客戶端系統內建的。所以,從這裡可以看出,如果使用 CA 認證的證書,系統會自動信任服務端公鑰來源;如果使用自簽名的證書,就需要客戶端提前內建該自簽名的證書,當收到服務端發來的證書時,需要與自己內建的證書進行比對,無誤後才可以信任,否則會有被中間人攻擊的風險。
在 Android 端,校驗證書的方式可以參考鴻洋-Android Https相關完全解析
如果考慮到一種極端情況,中間人所用的證書也是向 CA 機構申請的,那麼處理方式就和自簽名證書一樣,將服務端的證書提前放在本地,建立 HTTPS 連線的時候,將伺服器傳送來的證書與本地的證書進行嚴格比對。
總結
以上就是 HTTPS 加密的大致流程,它在一定程度上解決了 HTTP 協議明文傳輸的痛點,但是我們得清楚,世界上並不存在完全安全的系統,儘管 HTTPS 的加密機制的設計已經足夠精妙了,但它也並不是無懈可擊的。在 Android 端,我們可以使用 Xposed 或者其他 hook 框架對校驗證書的方法進行 hook,使其在任何情況下都校驗通過,這樣就繞過了證書校驗的過程。
加密與破解的過程本來就是魔高一尺,道高一丈的過程,再精妙絕倫的加密演算法也不是無懈可擊的,但這並不能否定加密的意義。就像再安全堅固的防盜門也會被撬開,但這並不能說防盜門的存在就沒有意義。安全機制的演進就是不斷提高破解成本的過程,當破解成本大於破解後的收益的時候,那就是安全的。