有了這些前置知識(shí),下面就來(lái)深入剖析 HTTPS 。
裸奔的 HTTP
為什么需要 HTTPS ?因?yàn)?HTTP 在裸奔。
針對(duì)上篇文章中提到過(guò)的安全傳輸信息的幾個(gè)要素:
- 保證傳輸內(nèi)容的安全,即不傳輸明文
- 防止傳輸內(nèi)容被篡改,即可以識(shí)別篡改
- 確認(rèn)對(duì)方真的是對(duì)方,即通信雙方身份的認(rèn)證
由于 HTTP 是 明文傳輸?shù)?/strong> ,也沒(méi)有提供身份驗(yàn)證的方式,任何人都可以在通信鏈路上的任意一個(gè)節(jié)點(diǎn)攔截,偽造通信內(nèi)容。所以 HTTP 沒(méi)有滿足上面幾條要素的任意一條,毫無(wú)安全性可言。在錯(cuò)綜復(fù)雜的現(xiàn)代互聯(lián)網(wǎng)環(huán)境下,無(wú)疑是行不通的,這也正是 HTTPS 得以迅速發(fā)展的原因。
Chrome 對(duì)于 HTTPS 鏈接會(huì)在地址欄顯示綠色小鎖;Android 9 開(kāi)始默認(rèn)啟用 TLS,如果需要使用 HTTP,需要進(jìn)行單獨(dú)配置;iOS 強(qiáng)制使用 HTTPS ;HTTP/2 雖然仍然支持明文傳輸,但 Chrome,F(xiàn)ireFox 公開(kāi)宣布只支持加密的 HTTP/2;HTTP/3 (QUIC) 內(nèi)置 TLS 1.3,只能進(jìn)行加密通信 … 事實(shí)上,HTTPS 已經(jīng)無(wú)處不在了。相信有一天,HTTP 將不復(fù)存在。
HTTPS = HTTP + ?
HTTP 將不復(fù)存在?這其實(shí)是個(gè)偽命題。事實(shí)上,HTTP 將永遠(yuǎn)存在。因?yàn)?HTTPS 并不是一個(gè)全新的產(chǎn)物,它是基于 HTTP 的。
我們回顧一下 TCP/IP 分層模型 和 OSI 參考模型 。
OSI 參考模型對(duì)通信過(guò)程中必要的功能進(jìn)行了歸納,但其只是一個(gè)模型,對(duì)各層的作用做了一系列粗略的界定。TCP/IP 協(xié)議分層與 OSI 參考模型略微不同,將傳輸層以上全部歸為應(yīng)用層。上圖中的 TCP/IP 協(xié)議只分了四層,但一些資料中會(huì)將其分為五層,加上了物理層,倒也并不影響理解。
HTTP 屬于應(yīng)用層協(xié)議,它直接與用戶交互,但并不負(fù)責(zé)真正的數(shù)據(jù)傳輸,它依賴于傳輸層協(xié)議 (一般是 TCP) 來(lái)將數(shù)據(jù)發(fā)送到對(duì)端。常見(jiàn)的傳輸層協(xié)議有 TCP 和 UDP 。同樣,傳輸層也并不真正進(jìn)行數(shù)據(jù)傳輸,它又依賴于網(wǎng)絡(luò)層協(xié)議,一般是 IP 協(xié)議。網(wǎng)絡(luò)層依賴鏈接層和物理設(shè)備進(jìn)行真正的數(shù)據(jù)傳輸。正是得益于良好的分層結(jié)構(gòu),讓我們可以很方便的實(shí)現(xiàn) HTTPS 。
有這樣一句廣泛流傳的話:計(jì)算機(jī)科學(xué)領(lǐng)域里的任何問(wèn)題,都可以通過(guò)引入一個(gè)中間層來(lái)解決。(如果不行,那么就再來(lái)一層!) 用這句話來(lái)形容 HTTPS 是再適合不過(guò)了。
在原來(lái)的分層協(xié)議中,應(yīng)用層直接將明文數(shù)據(jù)交給傳輸層來(lái)處理。而在 HTTPS 中, 應(yīng)用層和傳輸層之間加了一層 TLS 來(lái)負(fù)責(zé)數(shù)據(jù)的加密,這樣一來(lái),應(yīng)用層和傳輸層無(wú)需任何改變,就可以安全傳輸信息了。所以除了 HTTP,理論上任何應(yīng)用層協(xié)議都可以基于 TLS 進(jìn)行安全傳輸,例如 FTPS,SMTP…
TLS 的前身是 SSL 。SSL(Secure Sockets Layer) 是網(wǎng)景公司設(shè)計(jì)的安全傳輸協(xié)議,有 1.0,2.0,3.0 三個(gè)版本,但目前均已棄用?;ヂ?lián)網(wǎng)工程組 IETF 將 SSL 標(biāo)準(zhǔn)化,并改名為 TLS 。1999 年 發(fā)布了 TLS 1.0,2006 年發(fā)布了 TLS 1.1,2008 年發(fā)布了 TLS 1.2,2018 年發(fā)布了 TLS 1.3 。每個(gè)新版本都強(qiáng)化了性能和安全性,目前使用最為廣泛的是 TLS 1.2 ,之前的版本都將在今年被廢棄。
說(shuō)了半天 HTTPS ,那么它到底是如何運(yùn)作的呢?我聽(tīng)很多朋友抱怨過(guò),流程太復(fù)雜,看過(guò)一段時(shí)間就忘了。我在這里強(qiáng)烈建議大家用 wireshark 抓包分析一遍,再親手畫(huà)一個(gè)流程圖,這樣很容易就記住了。
認(rèn)證 密鑰協(xié)商 數(shù)據(jù)加密
HTTPS 的整體思路很簡(jiǎn)單,它其實(shí)就是做了三件事:認(rèn)證、密鑰協(xié)商、數(shù)據(jù)加密 。
-
通信雙方身份的驗(yàn)證
-
通信雙方協(xié)商出一個(gè)安全的會(huì)話密鑰,注意中間人攻擊的問(wèn)題
-
使用會(huì)話密鑰對(duì)稱加密通信內(nèi)容
看起來(lái)很簡(jiǎn)單,但 HTTPS 做了大量的工作來(lái)保證通信的安全。下面就來(lái)實(shí)戰(zhàn)抓包來(lái)學(xué)習(xí) HTTPS 的通信流程。
HTTPS 通信流程
下文以瀏覽器訪問(wèn) zhihu.com 抓取到的實(shí)際通信流程進(jìn)行分析。
建立 TCP 連接
TLS 是基于 TCP 連接上建立的安全層,所以第一步 三次握手 (SYN => SYN, ACK => ACK) 建立 TCP 連接是必不可少的。
Client Hello
建立 TCP 連接之后,瀏覽器率先發(fā)出 Client Hello 消息。
挑幾個(gè)重點(diǎn)字段說(shuō)一下。
Version 表示客戶端最高支持的 TLS 版本,向下兼容。上圖中是 TLS 1.2 (0x0301) 。
Random 是客戶端生成的一個(gè)隨機(jī)數(shù),后面用于生成主密鑰。下文中用 client_random 表示。Random 是 32 字節(jié),但其實(shí)隨機(jī)數(shù)的長(zhǎng)度是 28 字節(jié),前面四個(gè)字節(jié)是 UNIX 時(shí)間戳,并沒(méi)有什么意義。
Session ID 傳遞給服務(wù)器用于復(fù)用緩存的 TCP 連接。這里 Session ID 是有值的,但并不代表就一定會(huì)復(fù)用之前的連接,這要看服務(wù)器是否能找到該 Session ID 的連接。
Cipher Suites 是客戶端支持的密碼套件列表,服務(wù)器會(huì)從中選擇合適的密碼套件,排在第一個(gè)的優(yōu)先選擇。密碼套件是 TLS 協(xié)議的核心,可以說(shuō)它是保證 TLS 安全性的根本。密碼套件決定了 TLS 使用的身份認(rèn)證、密鑰交換、對(duì)稱加密、消息認(rèn)證碼的算法。在 TLS 1.2 中可選擇的密碼套件比較多,但在 TLS 1.3 中進(jìn)行了刪減,去除了部分不再安全的密碼套件。
Compression Methods 表示客戶端支持的壓縮方法。由于存在安全性問(wèn)題,一般不啟用,值為 null 。
Extension 為擴(kuò)展字段,可以讓客戶端和服務(wù)器在不更新 TLS 版本的基礎(chǔ)上獲取更多的能力??蛻舳丝梢园l(fā)送服務(wù)端不理解的擴(kuò)展,但服務(wù)端不能返回客戶端無(wú)法理解的擴(kuò)展,否則將發(fā)生錯(cuò)誤。另外在 TLS 1.3 中,為了保證向下兼容性,并沒(méi)有去修改 Version 字段,而是通過(guò) Supported Version: TLS 1.3 這樣的擴(kuò)展字段來(lái)說(shuō)明支持 TLS 1.3 。
Server Hello
服務(wù)端在收到 Client Hello 之后,根據(jù)客戶端發(fā)來(lái)的消息內(nèi)容,作出回應(yīng)。
Version 表示服務(wù)器選定使用的 TLS 版本,上圖中是 TLS 1.2 (0x0303) 。
Random 是服務(wù)器生成的隨機(jī)數(shù),其作用和 client_random 一樣,也是用來(lái)計(jì)算主密鑰,下文中用 server_random 表示?,F(xiàn)在瀏覽器,服務(wù)器都擁有了 client_random 和 server_random 兩個(gè)隨機(jī)數(shù)。
Session ID 為 null 表示服務(wù)器沒(méi)有可復(fù)用的 TCP 連接。因?yàn)槲夷M的第一次建立 TCP 連接的完整的 HTTPS 通信流程,所以必然是沒(méi)有復(fù)用的。如果 Session ID 不為空的話,其實(shí)走的是一個(gè)連接的恢復(fù)流程,這樣就抓不到完整的 HTTPS 流程了。后面可以簡(jiǎn)單演示一下。
Cipher Suite 表示服務(wù)端選定的密碼套件是 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 。簡(jiǎn)單畫(huà)個(gè)圖分析一下。
后續(xù)的整個(gè)加密流程都會(huì)遵循該密碼套件。
密鑰協(xié)商算法 選定了 ECDHE (橢圓曲線迪菲-赫爾曼密鑰交換) 。大多數(shù)資料中介紹的都是使用 RSA ,密鑰協(xié)商算法的不同會(huì)導(dǎo)致后續(xù)通信流程的不同,后面會(huì)詳細(xì)介紹。
身份驗(yàn)證算法 其實(shí)就是驗(yàn)證服務(wù)器證書(shū)簽名的,這里是 RSA 。
對(duì)稱加密算法 是用來(lái)加密通信數(shù)據(jù)的。
摘要算法 用于隨機(jī)數(shù)生成以及 HMAC 算法。
Certificate
服務(wù)器在發(fā)送 Server Hello 之后,會(huì)立馬發(fā)送服務(wù)器的證書(shū)鏈信息。其實(shí) Certificate 和 Server Hello 是在同一個(gè)數(shù)據(jù)包里面的,以降低延遲。
下圖是知乎服務(wù)器返回的證書(shū)鏈,可以看到有兩張,zhihu.com 的服務(wù)器證書(shū)和中間證書(shū)。注意,根證書(shū)通常不包含在其中。因?yàn)楦C書(shū)就在計(jì)算機(jī)中,沒(méi)有必要再去傳輸。
兩張證書(shū)的簽名算法都是 sha256WithRSA ,公鑰也返回給了客戶端,客戶端可以進(jìn)行證書(shū)驗(yàn)證。驗(yàn)證不通過(guò),就沒(méi)有辦法進(jìn)行下面的交互了。
暫停一下 …
下面的通信流程會(huì)因?yàn)槊荑€交換算法的不同,產(chǎn)生一些區(qū)別。所以這里先暫停一下,畫(huà)張圖總結(jié)一下上面的流程。
到目前為止,瀏覽器,服務(wù)器都持有了 client_random 和 server_random 。瀏覽器也拿到了服務(wù)器的證書(shū),可以對(duì)服務(wù)器進(jìn)行身份認(rèn)證。
接下來(lái)要做的就是協(xié)商密鑰了。但這里協(xié)商的并不是會(huì)話密鑰,而是一個(gè)叫做 pre_master 的預(yù)備主密鑰。還記得服務(wù)端選定的密碼套件嗎?TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 ,該密碼套件指定的密鑰協(xié)商算法是 ECDHE ,這是目前比較常用的算法,另外還可以使用 RSA 進(jìn)行密鑰協(xié)商,現(xiàn)在已經(jīng)不是很常用了,TLS 1.3 已經(jīng)廢棄了 RSA 密鑰協(xié)商。但大多數(shù)文章中說(shuō)的還都是 RSA 算法。
RSA 密鑰協(xié)商很簡(jiǎn)單。瀏覽器生成一個(gè)隨機(jī)數(shù),使用服務(wù)器公鑰加密之后發(fā)送給服務(wù)器,服務(wù)器接收之后使用自己的私鑰解密拿到隨機(jī)數(shù)。這個(gè)隨機(jī)數(shù)就是 pre_master。但是這個(gè)方案不具備 前向安全性 。
在 TLS 握手階段,中間人可以拿到 client_random, server_random 以及加密的 pre_master 。由于沒(méi)有服務(wù)器私鑰,中間人沒(méi)有辦法進(jìn)行解密,只能將加密的歷史通信數(shù)據(jù)保存下來(lái)。也正是因?yàn)榉?wù)器私鑰是不會(huì)變化的,一旦通過(guò)社會(huì)工程學(xué)或者其他因素導(dǎo)致的私鑰泄露,所有歷史通信數(shù)據(jù)都會(huì)被破解。所以,最好的方案是一次一密。準(zhǔn)確的說(shuō)是,每個(gè) TCP 連接都使用不同的密鑰。這正是 ECDHE 密鑰交換所能提供的特性。
知乎目前也是采用的 ECDHE 來(lái)協(xié)商密鑰,繼續(xù)分析下去。
Server Key Exchange
這是一條服務(wù)器發(fā)送給瀏覽器的消息。注意如果使用 RSA 生成 pre_master 的話,是沒(méi)有這條消息的,因?yàn)椴恍枰?wù)器再提供任何參數(shù)了。
我并不了解 ECDHE 的具體數(shù)學(xué)原理,只能大概闡述一下。服務(wù)端返回了 EC Diffie-Hellman Server Params ,可以理解為密鑰交換服務(wù)器需要準(zhǔn)備的參數(shù),包括命名曲線,DH 公鑰,簽名信息等等。同樣,瀏覽器也會(huì)準(zhǔn)備需要的參數(shù),一般就是一個(gè) DH 公鑰。雙方利用這些公開(kāi)的信息就可以協(xié)商出 pre_master。
這些參數(shù)中間人都可以拿到,但中間人是算不出 pre_master 的。關(guān)于具體的數(shù)學(xué)原理,你可以在網(wǎng)絡(luò)上搜索一下 。
Server Hello Done
一條固定格式的消息,用來(lái)通知瀏覽器我該提供的都提供完了,你可以干你的事情了。
這里,我想問(wèn)一個(gè)問(wèn)題:Server Hello Done 消息發(fā)送完成之前,瀏覽器進(jìn)行服務(wù)器證書(shū)校驗(yàn)了嗎? 你可以思考一下。
答案是 沒(méi)有。 因?yàn)?Server Hello 、Certificate、Server Key Exchange、Server Hello Done 這幾條消息其實(shí)都是在同一個(gè) TCP 數(shù)據(jù)包中的。拆分為多個(gè)包,只會(huì)徒增網(wǎng)絡(luò)延遲。
Client Key Exchange
瀏覽器收到 Server Hello Done 之后會(huì)立馬校驗(yàn)服務(wù)器證書(shū)。校驗(yàn)通過(guò)之后開(kāi)始協(xié)商 pre_master 。
如果密鑰協(xié)商算法是 RSA ,瀏覽器直接生成一個(gè)隨機(jī)數(shù),用服務(wù)器公鑰加密發(fā)送過(guò)去即可。
知乎使用的是 ECDHE 來(lái)協(xié)商密鑰,向服務(wù)器發(fā)送了 EC Diffie-Hellman Client Params ,如下圖所示。這時(shí)候服務(wù)器、瀏覽器都擁有了 Server Params 和 Client Params ,雙方利用同樣的信息計(jì)算出 pre_master 。
如何計(jì)算會(huì)話密鑰 ?
目前為止,雙方共同擁有的信息是 client_random、server_random、pre_master 。那么,如何計(jì)算出會(huì)話密鑰呢?
首先,根據(jù)客戶端隨機(jī)數(shù),服務(wù)器隨機(jī)數(shù),預(yù)備主密鑰通過(guò)特定算法計(jì)算出 48 位的 主密鑰(master_secret)。這個(gè)特定算法稱為 密鑰衍生算法,TLS 使用的密鑰衍生算法叫做 PRF ,可以列一個(gè)簡(jiǎn)單的表達(dá)式:
master_secret = PRF(pre_master_secret , “master_secret” , client_random + server_random)[0…47] ;
PRF 函數(shù)有三個(gè)參數(shù),**secret,label 和 seed **。client_random 和 server_random 合成了最后一個(gè)參數(shù) seed 。由于計(jì)算機(jī)無(wú)法生成真正的隨機(jī)數(shù),client_random 和 server_random 的作用就是盡量提高隨機(jī)性,保證不可預(yù)測(cè)。
自我介紹一下,小編13年上海交大畢業(yè),曾經(jīng)在小公司待過(guò),也去過(guò)華為、OPPO等大廠,18年進(jìn)入阿里一直到現(xiàn)在。
深知大多數(shù)初中級(jí)Android工程師,想要提升技能,往往是自己摸索成長(zhǎng)或者是報(bào)班學(xué)習(xí),但對(duì)于培訓(xùn)機(jī)構(gòu)動(dòng)則近萬(wàn)的學(xué)費(fèi),著實(shí)壓力不小。自己不成體系的自學(xué)效果低效又漫長(zhǎng),而且極易碰到天花板技術(shù)停滯不前!
因此收集整理了一份《2024年Android移動(dòng)開(kāi)發(fā)全套學(xué)習(xí)資料》,初衷也很簡(jiǎn)單,就是希望能夠幫助到想自學(xué)提升又不知道該從何學(xué)起的朋友,同時(shí)減輕大家的負(fù)擔(dān)。
既有適合小白學(xué)習(xí)的零基礎(chǔ)資料,也有適合3年以上經(jīng)驗(yàn)的小伙伴深入學(xué)習(xí)提升的進(jìn)階課程,基本涵蓋了95%以上Android開(kāi)發(fā)知識(shí)點(diǎn),真正體系化!
由于文件比較大,這里只是將部分目錄截圖出來(lái),每個(gè)節(jié)點(diǎn)里面都包含大廠面經(jīng)、學(xué)習(xí)筆記、源碼講義、實(shí)戰(zhàn)項(xiàng)目、講解視頻,并且會(huì)持續(xù)更新!
如果你覺(jué)得這些內(nèi)容對(duì)你有幫助,可以掃碼獲?。。。▊渥ⅲ篈ndroid)

最后
我見(jiàn)過(guò)很多技術(shù)leader在面試的時(shí)候,遇到處于迷茫期的大齡程序員,比面試官年齡都大。這些人有一些共同特征:可能工作了7、8年,還是每天重復(fù)給業(yè)務(wù)部門(mén)寫(xiě)代碼,工作內(nèi)容的重復(fù)性比較高,沒(méi)有什么技術(shù)含量的工作。問(wèn)到這些人的職業(yè)規(guī)劃時(shí),他們也沒(méi)有太多想法。
其實(shí)30歲到40歲是一個(gè)人職業(yè)發(fā)展的黃金階段,一定要在業(yè)務(wù)范圍內(nèi)的擴(kuò)張,技術(shù)廣度和深度提升上有自己的計(jì)劃,才有助于在職業(yè)發(fā)展上有持續(xù)的發(fā)展路徑,而不至于停滯不前。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-847950.html
不斷奔跑,你就知道學(xué)習(xí)的意義所在!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-847950.html
《Android學(xué)習(xí)筆記總結(jié)+移動(dòng)架構(gòu)視頻+大廠面試真題+項(xiàng)目實(shí)戰(zhàn)源碼》,點(diǎn)擊傳送門(mén)即可獲??!
法。
其實(shí)30歲到40歲是一個(gè)人職業(yè)發(fā)展的黃金階段,一定要在業(yè)務(wù)范圍內(nèi)的擴(kuò)張,技術(shù)廣度和深度提升上有自己的計(jì)劃,才有助于在職業(yè)發(fā)展上有持續(xù)的發(fā)展路徑,而不至于停滯不前。
不斷奔跑,你就知道學(xué)習(xí)的意義所在!
《Android學(xué)習(xí)筆記總結(jié)+移動(dòng)架構(gòu)視頻+大廠面試真題+項(xiàng)目實(shí)戰(zhàn)源碼》,點(diǎn)擊傳送門(mén)即可獲??!
到了這里,關(guān)于HTTPS 為什么是安全的 _ (下)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!