眾所周知,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,使其在任何情況下都校驗通過,這樣就繞過了證書校驗的過程。
加密與破解的過程本來就是魔高一尺,道高一丈的過程,再精妙絕倫的加密算法也不是無懈可擊的,但這并不能否定加密的意義。就像再安全堅固的防盜門也會被撬開,但這并不能說防盜門的存在就沒有意義。安全機制的演進就是不斷提高破解成本的過程,當破解成本大于破解后的收益的時候,那就是安全的。
參考文章
HTTPS 如何保證數據傳輸的安全性
扯一扯HTTPS單向認證、雙向認證、抓包原理、反抓包策略
Android Https相關完全解析 當OkHttp遇到Https