HTTPS 是建立在 SSL/TLS 傳輸層安全協(xié)議之上的一種 HTTP 協(xié)議,相當(dāng)于 HTTPS = HTTP + SSL/TLS。第一篇文章 “HTTPS - 通俗易懂的闡述 HTTPS 協(xié)議,解決面試難題” 更多是理論上的一些闡述,能解決一些面試及常見問題,例如 “SSL/TLS” 的關(guān)系是什么?文中都有介紹。本文通過對一次 TLS 握手過程的數(shù)據(jù)抓包分析做為切入點(diǎn),希望能進(jìn)一步的幫助大家理解 HTTPS 原理。
TLS 協(xié)議
TLS 是一種密碼學(xué)協(xié)議,保證了兩個(gè)端點(diǎn)之間的會(huì)話安全,一種最好的學(xué)習(xí)方法是使用抓包工具,捕獲網(wǎng)絡(luò)數(shù)據(jù)包,基于這些真實(shí)的數(shù)據(jù)包能夠有一些直觀的感受,例如:Wireshark,它可以捕獲 HTTP、TCP、TLS 等各種網(wǎng)絡(luò)協(xié)議數(shù)據(jù)包,是我們學(xué)習(xí)的好工具。
TLS 定義了四個(gè)核心子協(xié)議:握手協(xié)議 (handshake protocol)、密鑰規(guī)格變更協(xié)議 (change cipher spec protocol)、應(yīng)用數(shù)據(jù)協(xié)議 (application data protocol) 和警報(bào)協(xié)議 (alert protocol),這里最主要、最復(fù)雜是“握手協(xié)議”,協(xié)商對稱密碼就是在該協(xié)議中完成的。
來源:https://hpbn.co/assets/diagrams/9873c7441be06e0b53a006aac442696c.svg
握手過程圖示
參考 “網(wǎng)絡(luò)協(xié)議那些事兒 - 如何抓包并破解 HTTPS 加密數(shù)據(jù)?”,本文是抓取的 www.imooc.com 網(wǎng)站數(shù)據(jù)包,基于 TLS v1.2 協(xié)議未對數(shù)據(jù)包做解密處理。
下圖展示了 HTTPS 鏈接建立、TLS 握手協(xié)議里參數(shù)傳遞、證書驗(yàn)證、協(xié)商對稱密鑰的過程,更詳細(xì)的內(nèi)容,下文會(huì)介紹。
tls-1-2-full-handshake.jpg
握手協(xié)議
握手協(xié)議是 TLS 協(xié)議中最復(fù)雜的一部分,在這個(gè)過程中雙方會(huì)協(xié)商鏈接參數(shù)(TLS 版本號、隨機(jī)數(shù)等)并完成身份驗(yàn)證。里面可能會(huì)存在幾種情況:完整握手,對服務(wù)器進(jìn)行身份驗(yàn)證、恢復(fù)之前的會(huì)話采用的簡短握手、對客戶端和服務(wù)器都進(jìn)行身份驗(yàn)證握手,下文以完整握手為例。
在建立 TCP 鏈接之后,每一個(gè) TLS 鏈接都會(huì)以握手協(xié)議開始,完整握手是客戶端與服務(wù)器之前未建立會(huì)話,在第一次會(huì)話時(shí)會(huì)經(jīng)歷一次完整的握手。
Client Hello
在一次新的握手協(xié)議中,客戶端(瀏覽器)首先發(fā)出的一條消息是 “Client Hello”,告訴服務(wù)器我將給你傳遞這些數(shù)據(jù):
- Version:客戶端支持的最佳協(xié)議版本號。
- Random:客戶端提供給服務(wù)器的隨機(jī)數(shù),在每次握手中都會(huì)重新生成,這個(gè)隨機(jī)數(shù)用于后續(xù)生成密鑰。
- Session ID:會(huì)話 ID 在第一次鏈接時(shí)該字段是空的,表示客戶端并不希望恢復(fù)某個(gè)已存在的會(huì)話。
- Cipher Suites:客戶端所支持的所有秘密套件,按優(yōu)先級順序排列。
- Handshake Protocol: Client Hello
- Handshake Type: Client Hello (1)
- Length: 223
- Version: TLS 1.2 (0x0303)
- Random: b0fcb3aca27c6de8b0e4f146b92d33f24e6a671e62f8f6f669aabbfc19bb4326
- Session ID Length: 0
- Cipher Suites Length: 92
- Cipher Suites (46 suites)
- Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
- Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
- Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
- ...
Server Hello
“Server Hello” 是服務(wù)器在收到客戶端 “Client Hello” 之后的一個(gè)回應(yīng),告訴客戶端服務(wù)器的協(xié)議版本、服務(wù)器也會(huì)給出一個(gè)隨機(jī)數(shù) Random 用于后續(xù)生成密鑰,Cipher Suite 是從客戶端 “Client Hello” 消息的 Cipher Suites 里選擇的一個(gè)密碼套件。
- Handshake Protocol: Server Hello
- Handshake Type: Server Hello (2)
- Length: 89
- Version: TLS 1.2 (0x0303)
- Random: 616d836f609800aaa1713462f61d50cc6472c45b54c0ac58dd52b9db4d555f6f
- Session ID Length: 32
- Session ID: 279fb99351526e29a4ce41af4cbff5575933e5c45dff7a2016a16cdf414f22c2
- Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
了解密碼套件構(gòu)成
Certificate, Server Key Exchange, Server Hello Done
在 “Server Hello” 之后,服務(wù)器緊跟隨著發(fā)出 “Certificate, Server Key Exchange, Server Hello Done” 這三個(gè)消息告知客戶端。
Certificate(發(fā)送服務(wù)器證書信息到客戶端)
證書信息,典型的 Certificate 消息用于攜帶服務(wù)器 X.509 證書鏈,一個(gè)接一個(gè)組合而成,主證書第一個(gè),之后中間證書和根證書,服務(wù)器的公鑰也包含在證書信息中。
- Handshake Protocol: Certificate
- Handshake Type: Certificate (11)
- Length: 2781
- Certificates Length: 2778
- Certificates (2778 bytes)
- Certificate Length: 1407
- Certificate: 3082057b30820463a0030201020210040f1f824b17ca53814dc5c6f4c6a0a8300d06092a… (id-at-commonName=*.imooc.com)
- Certificate Length: 1365
- Certificate: 3082055130820439a003020102021007983603ade39908219ca00c27bc8a6c300d06092a… (id-at-commonName=RapidSSL TLS DV RSA Mixed SHA256 2020 CA-1,id-at-organizationName=DigiCert Inc,id-at-countryName=US)
這個(gè)證書鏈在瀏覽器地址欄點(diǎn)擊域名前面的 “小鎖”,可看到如下信息,最上面是根證書、中間(RapidSSL)是中級證書頒發(fā)機(jī)構(gòu)、*.imooc.com 這個(gè)是 CA 頒發(fā)給我們的域名證書。
Server Key Exchange(密鑰交換)
“Server Key Exchange” 消息是攜帶密鑰交換算法需要的額外數(shù)據(jù),目的是計(jì)算主密鑰需要的另一個(gè)值:“預(yù)主密鑰(premaster secret)”。
不同的算法套件對應(yīng)的消息內(nèi)容也是不同的,下面 EC Diffie-Hellman(簡稱 ECDHE)就是密鑰交換算法,這個(gè)對應(yīng) “Server Hello” 消息中選擇的密碼套件 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 中的 ECDHE。
下面 Server Params 中的 Curve Type 表示曲線類型,本次選中的橢圓曲線名稱為 named_curve:secp256r1,再確定基點(diǎn) G,此時(shí)還會(huì)選擇生成一個(gè)隨機(jī)數(shù)做為服務(wù)端橢圓曲線的私鑰,存放到本地,再根據(jù)基點(diǎn) G 和橢圓曲線的私鑰計(jì)算出橢圓曲線公鑰(這里的橢圓曲線公/私鑰都是臨時(shí)的,只對本次鏈接生效),名字為 Pubkey 傳遞給客戶端。
為了確保橢圓曲線公鑰信息不被篡改,將 Server Params 與客戶端和服務(wù)器隨機(jī)值連在一起使用私鑰簽名,客戶端從證書中獲得服務(wù)器的公鑰,就可驗(yàn)證是否來自服務(wù)器。客戶端和服務(wù)器的隨機(jī)值對于一次握手是唯一的,這也意味著攻擊者無法重復(fù)利用該簽名。
- Handshake Protocol: Server Key Exchange
- Handshake Type: Server Key Exchange (12)
- Length: 329
- EC Diffie-Hellman Server Params
- Curve Type: named_curve (0x03)
- Named Curve: secp256r1 (0x0017)
- Pubkey Length: 65
- Pubkey: 049c1c4eaa2ab8ae7b54482efc5d07e2b191174d804d660be07ded253c86f9bc5cd24f34…
- Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
- Signature Hash Algorithm Hash: SHA512 (6)
- Signature Hash Algorithm Signature: RSA (1)
- Signature Length: 256
- Signature: 5b9b1a750f0168f0a57852b4a77c14c351c5b97d7eb4a470fa8e3cf9e385cf7ac16f056f…
不同的密鑰交換算法,生成預(yù)主密鑰的方式也不同,我們這里的示例以 ECDHE 為主,還有一種密鑰交換算法是 RSA,它的密鑰交換過程很簡單,由客戶端生成預(yù)主密鑰,為 46 字節(jié)的隨機(jī)數(shù),使用服務(wù)器的公鑰加密,經(jīng)過“Client Key Exchange” 消息發(fā)送到服務(wù)端,服務(wù)端再用私鑰就可解密出這個(gè)預(yù)主密鑰。
基于 RSA 的密鑰交換算法被認(rèn)為存在嚴(yán)重的漏洞威脅,任何能夠接觸到私鑰的人(例如,由于政治、賄賂、強(qiáng)行進(jìn)入等)都可恢復(fù)預(yù)主密鑰,進(jìn)而構(gòu)建相同的主密鑰,最終密鑰泄漏就可解密之前記錄的所有流量了。這種密鑰交換算法正在被支持前向保密保密的其它算法替代,例如,我們示例中的 ECDHE 算法在密鑰交換時(shí),每個(gè)鏈接使用的主密鑰相互獨(dú)立,如果出現(xiàn)問題也只是影響到當(dāng)前會(huì)話,不能用于追溯解密任何其它的流量。
Server Hello Done
“Server Hello Done” 表示服務(wù)器已將握手消息需要的數(shù)據(jù)都發(fā)送完畢。之后就是等待客戶端的回應(yīng)。
- Handshake Protocol: Server Hello Done
- Handshake Type: Server Hello Done (14)
- Length: 0
Client Key Exchange(客戶端發(fā)送給服務(wù)器的密鑰交換信息)
“Client Key Exchange” 的消息也是攜帶密鑰交換需要的額外數(shù)據(jù),不過這一次是客戶端發(fā)送給服務(wù)端的,Client Params 里面提供了客戶端生成的臨時(shí)橢圓曲線公鑰信息。
- Handshake Protocol: Client Key Exchange
- Handshake Type: Client Key Exchange (16)
- Length: 66
- EC Diffie-Hellman Client Params
- Pubkey Length: 65
- Pubkey: 04c64110c2838d112d8fbc8a85a2c2b3b596e70d6ff9198330801df93ce9737432eeabe6…
客戶端驗(yàn)證證書和計(jì)算密鑰
現(xiàn)在一次 TCP 往返結(jié)束了,客戶端拿到了服務(wù)器的證書、Server Random、Server Params,現(xiàn)在客戶端需要驗(yàn)證證書合法性和計(jì)算一些加密信息。
驗(yàn)證服務(wù)器發(fā)來的證書合法性
客戶端收到服務(wù)器的響應(yīng)信息,驗(yàn)證證書的合法性,可回顧上一節(jié) 深入淺出 HTTPS 原理篇。如果證書校驗(yàn)通過繼續(xù)往下走。
計(jì)算預(yù)主密鑰
上面也提了,在 “Server Key Exchange” 消息中,服務(wù)器對 Server Params 用私鑰做了簽名,客戶端要從證書中獲得服務(wù)器公鑰,驗(yàn)證參數(shù)是否來自期望的服務(wù)器,這也是身份驗(yàn)證。
身份驗(yàn)證成功之后,得到 Server Params 參數(shù),而 Server Params 參數(shù)里包含了 “服務(wù)器密鑰交換消息” 中生成的臨時(shí)公鑰、secp256r1 橢圓曲線算法,現(xiàn)在客戶端使用 secp256r1 算法用這個(gè)臨時(shí)公鑰和客戶端自己生成的臨時(shí)私鑰相乘計(jì)算出預(yù)主密鑰(premaster secret)。
計(jì)算主密鑰
現(xiàn)在客戶端手里已經(jīng)有了 Client Random、Server Random、Premaster Secret 三個(gè)隨機(jī)參數(shù),調(diào)用 PRF 偽隨機(jī)函數(shù)函數(shù)生成 48 字節(jié)(384 位)主密鑰。
- master_secret = PRF(pre_master_secret, "master secret",
- ClientHello.random + ServerHello.random)
構(gòu)建會(huì)話密鑰
上面的主密鑰并不是最終的會(huì)話密鑰,最終的會(huì)話密鑰使用 PRF 偽隨機(jī)函數(shù)傳入主密鑰、客戶端隨機(jī)數(shù)、服務(wù)端隨機(jī)數(shù)生成。
- key_block = PRF(master_secret, "key expansion", server_random + client_random)
這個(gè)最終的會(huì)話密鑰包括:對稱加密密鑰(symmetric key)、消息認(rèn)證碼密鑰(mac key)、初始化項(xiàng)量(iv key,只在必要時(shí)生成)。
客戶端發(fā)出 Change Cipher Spec, Encrypted Handshake Message
當(dāng)客戶端完成密鑰計(jì)算操作后,還要給服務(wù)器發(fā)送切換加密模式、驗(yàn)證會(huì)話密碼消息。
Change Cipher Spec
“Change Cipher Spec” 消息表示客戶端已生成加密密鑰,并切換到加密模式。
- TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
- Content Type: Change Cipher Spec (20)
- Version: TLS 1.2 (0x0303)
- Length: 1
- Change Cipher Spec Message
注意:“Change Cipher Spec” 不屬于握手協(xié)議,它是另一種密鑰規(guī)格變更協(xié)議。
Encrypted Handshake Message
這個(gè)是將之前所有的握手?jǐn)?shù)據(jù)做一個(gè)摘要,再用最后協(xié)商好的對稱加密算法對數(shù)據(jù)做加密,通過 “Encrypted Handshake Message” 消息發(fā)送到服務(wù)器進(jìn)行校驗(yàn),這個(gè)對稱加密密鑰是否成功。
- TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
- Content Type: Handshake (22)
- Version: TLS 1.2 (0x0303)
- Length: 60
- Handshake Protocol: Encrypted Handshake Message
服務(wù)器計(jì)算密鑰
服務(wù)器在收到客戶端 “Client Key Exchange” 消息后,這時(shí)可以拿到 Client Random、Server Random、Client Params,先計(jì)算出預(yù)主密鑰后,再分別計(jì)算出主密鑰和最終的會(huì)話密鑰,這塊可參考客戶端計(jì)算密鑰一樣的。
服務(wù)器發(fā)出 Change Cipher Spec, Encrypted Handshake Message
Change Cipher Spec
服務(wù)器發(fā)出 “Change Cipher Spec” 消息告訴客戶端,服務(wù)端已生成密鑰,請求客戶端切換加密模式。
- TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
- Content Type: Change Cipher Spec (20)
- Version: TLS 1.2 (0x0303)
- Length: 1
Encrypted Handshake Message
“Encrypted Handshake Message” 這條消息也是服務(wù)器對握手的所有數(shù)據(jù)用協(xié)商好的對稱加密算法加密,供客戶端校驗(yàn)。
如果對抓取后的報(bào)文做解密,這里看到的是 “Finished” 消息。
- TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
- Content Type: Handshake (22)
- Version: TLS 1.2 (0x0303)
- Length: 40
- Handshake Protocol: Encrypted Handshake Message
應(yīng)用數(shù)據(jù)協(xié)議
整個(gè)握手過程完畢之后,我們會(huì)看到應(yīng)用數(shù)據(jù)協(xié)議 “Application Data Protocol: http-over-tls”,之后我們的客戶端/服務(wù)端建立一個(gè)安全通信隧道,就可以發(fā)送應(yīng)用程序數(shù)據(jù)了。
- TLSv1.2 Record Layer: Application Data Protocol: http-over-tls
- Content Type: Application Data (23)
- Version: TLS 1.2 (0x0303)
- Length: 101
- Encrypted Application Data: 1303136ee3f0e6daf0cb0e82d07fcca423c9cb2a26b29e332cdc604397f43c377df9805e…
- [Application Data Protocol: http-over-tls]
Reference
https://hpbn.co/transport-layer-security-tls/
HTTPS 權(quán)威指南
https://tls.ulfheim.net/
https://datatracker.ietf.org/doc/html/rfc5246
原文鏈接:https://mp.weixin.qq.com/s/SmX3itX8eG9MHLgEXQ_ntw