1,摘要
本文配圖介紹HTTPS協議的層級結構,訪問原理,交互過程,說明如何解決存在的中間人問題。
2,內容
2.1 HTTPS的協議棧層級
HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer 或 Hypertext Transfer Protocol Secure,超文本傳輸安全協議),是以安全為目標的HTTP通道,簡單講是HTTP的安全版。即HTTP下加入SSL層,HTTPS的安全基礎是SSL,因此加密的詳細內容就需要SSL。 它是一個URI scheme(抽象標識符體系),句法類同http:體系。用于安全的HTTP數據傳輸。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默認端口及一個加密/身份驗證層(在HTTP與TCP之間)。
為鼓勵全球網站的 HTTPS 實現,一些互聯網公司都提出了自己的要求:
1)Google 已調整搜索引擎算法,讓采用 HTTPS 的網站在搜索中排名更靠前;
2)從 2017 年開始,Chrome 瀏覽器已把采用 HTTP 協議的網站標記為不安全網站;
3)蘋果要求 2017 年 App Store 中的所有應用都必須使用 HTTPS 加密連接;
4)當前國內炒的很火熱的微信小程序也要求必須使用 HTTPS 協議;
5)新一代的 HTTP/2 協議的支持需以 HTTPS 為基礎。
因此,作為程序員來說,HTTPS知識必須掌握。
如上圖所示 HTTPS 相比 HTTP 多了一層 SSL/TLS
SSL(Secure Socket Layer,安全套接字層):1994年為 Netscape 所研發,SSL 協議位于 TCP/IP 協議與各種應用層協議之間,為數據通訊提供安全支持。
TLS(Transport Layer Security,傳輸層安全):其前身是 SSL,它最初的幾個版本(SSL 1.0、SSL 2.0、SSL 3.0)由網景公司開發,1999年從 3.1 開始被 IETF 標準化并改名,發展至今已經有 TLS 1.0、TLS 1.1、TLS 1.2 三個版本。SSL3.0和TLS1.0由于存在安全漏洞,已經很少被使用到。TLS 1.3 改動會比較大,目前還在草案階段,目前使用最廣泛的是TLS 1.1、TLS 1.2。
2.2 TCP的3次握手和HTTP 訪問過程
2.2.1 TCP的3次握手
客戶端輸入URL回車,DNS解析域名得到服務器的IP地址,服務器在80端口監聽客戶端請求,端口通過TCP/IP協議(可以通過Socket實現)建立連接。HTTP屬于TCP/IP模型中的運用層協議,所以通信的過程其實是對應數據的入棧和出棧。
報文從運用層傳送到運輸層,運輸層通過TCP三次握手和服務器建立連接,四次揮手釋放連接。
分析下這個三次握手的過程:
第一次握手:主機A發送位碼為syn=1,隨機產生seq number= X的數據包到服務器,主機B由SYN=1知道,A要求建立聯機;
第二次握手:主機B收到請求后要確認聯機信息,向A發送syn=1,ack number= X+1 ,隨機產生seq=Y的包
第三次握手:主機A收到后檢查ack number是否正確,即第一次發送的X+1,以及位碼SYN是否為1;若正確,主機A會再發送ack number=(Y+1), Seq = z,主機B收到后確認seq值與ack=1則連接建立成功。
完成三次握手,主機A與主機B開始傳送數據。
2.2.2 HTTP 訪問過程
抓包如下:
如上圖所示,HTTP請求過程中,客戶端與服務器之間沒有任何身份確認的過程,數據全部明文傳輸,“裸奔”在互聯網上,所以很容易遭到黑客的攻擊,如下:
可以看到,客戶端發出的請求很容易被黑客截獲,如果此時黑客冒充服務器,則其可返回任意信息給客戶端,而不被客戶端察覺,所以我們經常會聽到一詞“劫持”。所以 HTTP 傳輸面臨的風險有:
(1) 竊聽風險:黑客可以獲知通信內容。
(2) 篡改風險:黑客可以修改通信內容。
(3) 冒充風險:黑客可以冒充他人身份參與通信。
2.3 安全通信三原則和https的設計思路
2.3.1 確保安全通信的三個原則
A.數據內容的加密
這個很好理解是吧,敏感信息肯定要加密的,明文傳輸等于自殺。不過多解釋了。
B.通訊雙方的身份校驗
這個很多人不理解,這是啥意思,按道理說我們用非對稱加密應該就完美了啊。但是謹記我們的數據包不是從A直接到B的。
中間要經過無數次的路由器轉發等等,這個中間一旦有人截獲了我們的數據包,換成自己的數據包,就很危險了。
所以我們還需要一種機制能校驗通訊雙方的身份。確保我是在和我老婆說話 而不是在我和丈母娘說話。
C.數據內容的完整性
這個也不是很容易理解,按道理說TCP是能保證數據有序完整的到達對方的。但是不要忘記中間我們經過的無數次路由器轉發,
可能被劫持,被劫持以后可能會對數據包進行篡改,這個時候我們需要一種機制保護我們的數據不被篡改,即使被篡改也能被我們察覺,確保我對我老婆寫的信能完整的讓我老婆看到,而不是只看到一半。
2.3.2 https的設計思路
根據前面我們闡述的加密算法和安全通信三原則,為了保證我們的通信能夠安全進行,可以試想出一種流程來保證通信安全:
- 服務器為每個客戶端生成一個公鑰,將公鑰發送給客戶端;
- 客戶端選擇一個加密算法,然后用公鑰加密以后發送給服務器;
- 服務器收到這個公鑰加密后的算法以后拿自己的私鑰解密,然后就知道這個加密算法是哪個了。今后就一直用這個算法通信;
目前來看,這個思路是不是很完美。公鑰即使被中間人截獲以后也沒用,因為拿到公鑰也解密不出來到底雙方是用哪種算法加密的。
但有個重大缺陷:
中間人可以將服務器發送的公鑰包進行掉包,客戶端怎么知道這個公鑰是真的服務器發送的還是假的中間人給的非法公鑰呢?
可以看這張圖,基本上中間人攻擊就是這個圖所示的意思。
那有沒有一種方式既可以安全的獲取公鑰,又能防止黑客冒充呢? 那就需要用到終極武器了:SSL 證書申購了。
具體步驟說明:
如上圖所示,在第 ② 步時服務器發送了一個SSL證書給客戶端,SSL 證書中包含的具體內容有:
(1)證書的發布機構CA
(2)證書的有效期
(3)公鑰
(4)證書所有者
(5)簽名
………
客戶端在接受到服務端發來的SSL證書時,會對證書的真偽進行校驗,以瀏覽器為例說明如下:
(1)首先瀏覽器讀取證書中的證書所有者、有效期等信息進行一一校驗;
(2)瀏覽器開始查找操作系統中已內置的受信任的證書發布機構CA,與服務器發來的證書中的頒發者CA比對,用于校驗證書是否為合法機構頒發;
(3)如果找不到,瀏覽器就會報錯,說明服務器發來的證書是不可信任的;
(4)如果找到,那么瀏覽器就會從操作系統中取出 頒發者CA 的公鑰,然后對服務器發來的證書里面的簽名進行解密;
(5)瀏覽器使用相同的hash算法計算出服務器發來的證書的hash值,將這個計算的hash值與證書中簽名做對比;
(6)對比結果一致,則證明服務器發來的證書合法,沒有被冒充;
(7)此時瀏覽器就可以讀取證書中的公鑰,用于后續加密了;
所以通過發送SSL證書的形式,既解決了公鑰獲取問題,又解決了黑客冒充問題,一箭雙雕,HTTPS加密過程也就此形成。
所以相比HTTP,HTTPS 傳輸更加安全:
(1) 所有信息都是加密傳播,黑客無法竊聽。
(2) 具有校驗機制,一旦被篡改,通信雙方會立刻發現。
(3) 配備身份證書,防止身份被冒充。
2.3.3 加密知識普及
1、對稱加密
有流式、分組兩種,加密和解密都是使用的同一個密鑰。
例如:DES、AES-GCM、ChaCha20-Poly1305等。
【戲說】
對稱加密的一方(比如小紅)用秘鑰 K 給文本 M 加密;另一方(比如小明)用 同一個秘鑰解密:
小紅 : C = E(M, K)
小明 : M = D(C, K)
這有一個問題:當一方生成了秘鑰 K 之后得把 K 分享給另一方。但是穿越 Sin City 的道路危險中途很可能有人竊聽到 K,竊聽者就可以假扮雙方中的任何一 方與另一方通信。這叫中間人攻擊。
2、非對稱加密
加密使用的密鑰和解密使用的密鑰是不相同的,分別稱為:公鑰、私鑰,公鑰和算法都是公開的,私鑰是保密的。非對稱加密算法性能較低,但是安全性超強,由于其加密特性,非對稱加密算法能加密的數據長度也是有限的。
例如:RSA、DSA、ECDSA、 DH、ECDHE。
【戲說】
非對稱加密利用成對的兩個秘鑰:K1 和 K2。小紅用其中一個加密文本,小明可 以用另一個解密文本。比如,小紅用 K1 加密,小明用 K2 解密:
小紅 : C = E(M, K1)
小明 : M = D(C, K2)
這樣一來,雙方中的一方(比如小紅)可以生成 K1和K2,然后把其中一個秘鑰 (比如K1)私藏,稱為私鑰;另一個(比如K2)公開,稱為公鑰。另一 方(比如小明)得到公鑰之后,雙方就可以通信。
然而,中間人可能在小明獲取公鑰時截獲消息,然后自己弄一對秘鑰(κ1, κ2),然后 告訴小明說 κ2 是小紅的公鑰。這樣中間人每次可以用截獲的 K2 解密小紅發給 小明的文本(甚至可能修改文本),再用 κ1 加密了發出去;小明用 κ2 解密接收。
3、哈希算法
將任意長度的信息轉換為較短的固定長度的值,通常其長度要比信息小得多,且算法不可逆。
例如:MD5、SHA-1、SHA-2、SHA-256 等。
4、數字簽名
數字簽名技術是將摘要信息用發送者的私鑰加密,與原文一起傳送給接收者。接收者只有用發送者的公鑰才能解密被加密的摘要信息,然后用HASH函數對收到的原文產生一個摘要信息,與解密的摘要信息對比。如果相同,則說明收到的信息是完整的,在傳輸過程中沒有被修改,否則說明信息被修改過,因此數字簽名能夠驗證信息的完整性。
數字簽名是個加密的過程,數字簽名驗證是個解密的過程。
普通數字簽名算法有RSA、ElGamal、Fiat-Shamir、Guillou- Quisquarter、Schnorr、Ong-Schnorr-Shamir數字簽名算法、Des/DSA,橢圓曲線數字簽名算法和有限自動機數字簽名算法等。
HTTPS使用CA證書的傳輸方式就是使用了數字簽名,非對稱加密,對稱加密等混合加密技術。
數字簽名的做法是:
- 小紅把自己的公鑰和ID(身份證號碼,或者域名)合為身份證申請(certificate signing request,CSR),小紅把CSR發給一個德高望重的人(被稱為 certificate authority,CA),比如小亮。
- 小亮用自己的私鑰加密小紅的 CSR,得到的密文被稱為數字簽名(digital signature)。
- 小亮把 signature 和 CSR 的明文合在一起稱為 CA簽署的身份證(CA signed certificate,CRT),發給小紅。
小紅:CSR = 小紅公鑰+小紅域名
signature = E(CSR, 小亮的私鑰)
CRT = CSR + signature
每當其他人(比如小明)找小紅聊天(建立HTTPS連接)的時候,小紅出示自己的小亮簽署的身份證。 拿到這個身份證的人,只要他是相信小亮的——在自己機器上安裝了小亮的身份證,就可以從小亮的身份證中的小亮的CSR里提取小亮的公鑰;
然后用小亮的公鑰解密小紅的身份證中小亮的signature,得到一個小紅的CSR;
如果這個CSR'和小紅身份證中的CSR明文一致,則說明“這個小紅的身份證是小亮確認過并且簽名的”。
小明:小亮的公鑰 = 小亮的CRT.CSR.小亮的公鑰
CSR' = D(CRT.signature, 小亮的公鑰)
if CSR' == CRT.CSR then OK
2.4 HTTPS真實交互消息過程
2.4.1 HTTPS交互消息
說明:
(1)看藍色的部分是tcp鏈接。所以https的加密層也是在tcp之上的。
(2)客戶端首先發起clientHello消息。包含一個客戶端隨機生成的random1 數字,客戶端支持的加密算法,以及SSL信息。
(3)服務器收到客戶端的clientHello消息以后,取出客戶端法發來的random1數字,并且取出客戶端發來的支持的加密算法,
然后選出一個加密算法,并生成一個隨機數random2,發送給客戶端serverhello讓客戶端對服務器進行身份校驗,服務端通過將自己的公鑰通過數字證書的方式發送給客戶端。
(4)客戶端收到服務端傳來的證書后,先從 CA 驗證該證書的合法性,驗證通過后取出證書中的服務端公鑰,再生成一個隨機數 Random3,再用服務端公鑰非對稱加密 Random3 生成 PreMaster Key。并將PreMaster Key發送到服務端。
(5)服務端通過私鑰將PreMaster Key解密獲取到Random3,此時客戶端和服務器都持有三個隨機數Random1 Random2 Random3,雙方在通過這三個隨即書生成一個對稱加密的密鑰.雙方根據這三個隨即數經過相同的算法生成一個密鑰,而以后應用層傳輸的數據都使用這套密鑰進行加密。
Change Cipher Spec Finished:告訴客戶端以后的通訊都使用這一套密鑰來進行。
(6)最后ApplicationData 全部使用對稱加密的原因就是非對稱加密太卡,對稱加密不影響性能。所以實際上也看的出來,HTTPS的真正目的就是保證對稱加密的 密鑰不被破解,不被替換,不被中間人攻擊,如果發生了上述情況,那么HTTPS的加密層也能獲知,避免發生事故。
2.4.2 用WireShark還原一次HTTPS的交互過程
目標訪問地址就用github吧。 抓出來是這樣的。
注意看tlsv1的就可以了這個就是加密層。下面就來逐步分析:
(1) ClientHello (line-2330)
(2)severHello (line-2380)
注意到這里服務器和客戶端就有2個隨機數了。并且加密算法也確定了。
(3)Certificate / severHelloDone(line 2435)
這部分主要是發送證書信息的 點開以后 證書的詳細信息都能看到。另外serverhellodone的意思就是服務器的工作都完畢了。
(4)Client key exchange / ChangeCipherSpec (line-2449)
可以看出來這里一共有三個步驟,我們來依次分析 這三次動作都做了什么:
- Client Key Exchange
服務器收到這個random3的加密信息以后,用自己的私鑰解密,這樣服務器和客戶端就共同擁有了random 1,2,3這3組隨機數,然后用這三組數據生成一個密鑰,這個密鑰就是后面我們applicationdata交互時使用的對稱加密的密鑰了。
- ChangeCipherSpec
(5)Change Cipher Spec Finished /new session ticket(line 2926)
解釋參考圖片描述。
這個session ticket就是服務器最后一步的時候傳給客戶端的一個數據。
這個加密數據客戶端收到以后就可以保存下來,這樣下一次再請求https的時候,就可以把這個session ticket發過去,這樣可以省很多握手的時間和資源消耗。(前面我們分析的其實已經相當復雜了,尤其是非對稱加密對服務端的資源消耗相當之大),實際上對于多數瀏覽器來說,指向同一個域名的https連接,我們都會有意識的讓第一個https連接完成握手之后再連接第n個 https。因為這樣后續的https 就可以攜帶相關信息,可以省很多資源這個ticket實際上就有點類似cookie。
在筆者的這次訪問chrome-gitub的過程中,瀏覽器并沒有使用ticket技術而是使用的seession id技術:
sessionid 實際上作用和ticket差不多,但是sessionid 無法做到服務器之間同步,畢竟id 存在服務器內存中,負載均衡帶來的狀態機同步是一個大問題。
(6)Application Data (line-2964)
2.5 CA證書是收費的啊,我不想交錢咋辦呢?
可以自己制作證書,然后把這個證書的公鑰放在客戶端(例如app的安裝目錄下),這樣app只要使用自己的證書公鑰即可解密了,不需要使用系統的。但是這樣帶來的問題是,如果有人獲取到了你這個公鑰證書咋辦?
數字簽名認證算法即可保證此類問題,其實簡單來說就是服務器和客戶端事先約定好一種加密規則即可,就可以得知是否被篡改。
這部分由于不是重點,暫時不講的太細,只要知道有這么個事即可。實際上你弄懂整個https以后這個地方就自然而然也能想明白了。
參考《螞蟻區塊鏈第9課 SSL/TLS工作原理及在螞蟻BAAS中的應用》可了解SSL/TLS的原理和在螞蟻區塊鏈的應用。
3,參考
(1)HTTP和HTTPS協議,看一篇就夠了
https://blog.csdn.net/xiaoming100001/article/details/81109617
(2)深入理解HTTPS協議【優質】
https://juejin.im/post/5a2fbe1b51882507ae25f991
(3)HTTPS系列干貨(一):HTTPS 原理詳解
https://zhuanlan.zhihu.com/p/27395037
(4)HTTP協議入門教程,一文就夠了!
http://www.lxweimin.com/p/083f992d0ee3