HTTP 協(xié)議中的內(nèi)容都是明文傳輸,HTTPS 的目的是將這些內(nèi)容加密,確保信息傳輸安全。最后一個(gè)字母 S 指的是 SSL/TLS 協(xié)議,它位于 HTTP 協(xié)議與 TCP/IP 協(xié)議中間。
很遺憾的是,目前的 HTTP 協(xié)議還不滿足上述三條要求中的任何一條。
是的,我沒開玩笑,你可以暫時(shí)別管第三個(gè)要求,因?yàn)樗鼘?shí)際上隸屬于第一個(gè)需求。我們都知道加密需要密碼,密碼不是天下掉下來,也得需要雙方經(jīng)過通信才能協(xié)商出來。所以一個(gè)設(shè)計(jì)良好的加密機(jī)制必然會(huì)防止第三者的干擾和偽造。等搞明白了加密的具體原理,我們自然可以檢驗(yàn)是否滿足:“任何第三者無法冒充服務(wù)器”這一要求。
對(duì)稱加密可以理解為對(duì)原始數(shù)據(jù)的可逆變換。比如 Hello 可以變換成 Ifmmp,規(guī)則就是每個(gè)字母變成它在字母表上的后一個(gè)字母,這里的秘鑰就是 1,另一方拿到 Ifmmp 就可以還原成原來的信息 Hello 了。
引入對(duì)稱加密后,HTTPS 的握手流程就會(huì)多了兩步,用來傳遞對(duì)稱加密的秘鑰:
提到了對(duì)稱加密,那么自然還有非對(duì)稱加密。它的思想很簡(jiǎn)單,計(jì)算兩個(gè)質(zhì)數(shù)的乘積很容易,但反過來分解成兩個(gè)質(zhì)數(shù)的乘積就很難,要經(jīng)過極為復(fù)雜的運(yùn)算。非對(duì)稱加密有兩個(gè)秘鑰,一個(gè)是公鑰,一個(gè)是私鑰。公鑰加密的內(nèi)容只有私鑰可以解密,私鑰加密的內(nèi)容只有公鑰可以解密。一般我們把服務(wù)器自己留著,不對(duì)外公布的密鑰稱為私鑰,所有人都可以獲取的稱為公鑰。
使用對(duì)稱加密一般要比非對(duì)稱加密快得多,對(duì)服務(wù)器的運(yùn)算壓力也小得多。
服務(wù)器直接返回明文的對(duì)稱加密密鑰是不是不安全。如果有監(jiān)聽者拿到這個(gè)密鑰,不就知道客戶端和服務(wù)器后續(xù)的通信內(nèi)容了么?
是這樣,所以不能明文傳遞對(duì)稱秘鑰,而且也不能用一個(gè)新的對(duì)稱加密算法來加密原來的對(duì)稱秘鑰,否則新的對(duì)稱秘鑰同樣無法傳輸,這就是雞生蛋、蛋生雞的悖論。
這里我們引入非對(duì)稱加密的方式,非對(duì)稱加密的特性決定了服務(wù)器用私鑰加密的內(nèi)容并不是真正的加密,因?yàn)楣€所有人都有,所以服務(wù)器的密文能被所有人解析。但私鑰只掌握在服務(wù)器手上,這就帶來了兩個(gè)巨大的優(yōu)勢(shì):
所以傳輸對(duì)稱秘鑰的問題就迎刃而解了: 秘鑰不是由服務(wù)器下發(fā),而是由客戶端生成并且主動(dòng)告訴服務(wù)器。
所以當(dāng)引入非對(duì)稱加密后,HTTPS 的握手流程依然是兩步,不過細(xì)節(jié)略有變化:
客戶端: 你好,我需要發(fā)起一個(gè) HTTPS 請(qǐng)求,這是我的 (用公鑰加密后的) 秘鑰。
服務(wù)器: 好的,我知道你的秘鑰了,后續(xù)就用它傳輸。
你好像還是沒有解決雞生蛋,蛋生雞的問題。你說客戶端發(fā)送請(qǐng)求時(shí)要用公鑰加密對(duì)稱秘鑰,那公鑰怎么傳輸呢?
每一個(gè)使用 HTTPS 的服務(wù)器都必須去專門的證書機(jī)構(gòu)注冊(cè)一個(gè)證書,證書中存儲(chǔ)了用權(quán)威機(jī)構(gòu)私鑰加密的公鑰。這樣客戶端用權(quán)威機(jī)構(gòu)的公鑰解密就可以了。
現(xiàn)在 HTTPS 協(xié)議的握手階段變成了四步:
那權(quán)威機(jī)構(gòu)的公鑰又怎么傳輸?
這個(gè)公鑰不用傳輸,會(huì)直接內(nèi)置在各大操作系統(tǒng)(或者瀏覽器)的出廠設(shè)置里。之所以不把每個(gè)服務(wù)器的公鑰內(nèi)置在電腦里,一方面是因?yàn)榉?wù)器太多,存不過來。另一方面操作系統(tǒng)也不信任你,憑什么你說你這個(gè)就是百度/淘寶的證書呢?
所以各個(gè)公司要先去權(quán)威機(jī)構(gòu)認(rèn)證,申請(qǐng)證書,然后操作系統(tǒng)只會(huì)存儲(chǔ)權(quán)威機(jī)構(gòu)的公鑰。因?yàn)闄?quán)威機(jī)構(gòu)數(shù)量有限,所以操作系統(tǒng)廠商相對(duì)來說容易管理。如果這個(gè)權(quán)威機(jī)構(gòu)不夠權(quán)威,XJB 發(fā)證書,就會(huì)取消他的資格,比如可憐的沃通。。。。
你說服務(wù)器第一次會(huì)返回證書,也就是加密以后的公鑰,那我怎么知道這個(gè)證書是可靠的?
我們都知道哈希算法的特點(diǎn),它可以壓縮數(shù)據(jù),如果從函數(shù)角度來看,不管多復(fù)雜的數(shù)據(jù)(定義域可以非常大)經(jīng)過哈希算法都會(huì)得到一個(gè)值,而且這個(gè)值處在某個(gè)特定(遠(yuǎn)小于定義域的范圍)值域內(nèi)。相同數(shù)據(jù)的哈希結(jié)果一定相同,不相同數(shù)據(jù)的哈希結(jié)果一般不同,不過也有小概率會(huì)重復(fù),這叫哈希沖突。
為了確保原始證書沒有被篡改,我們可以在傳遞證書的同時(shí)傳遞證書的哈希值。由于第三者無法解析數(shù)據(jù),只能 XJB 改,那么修改后的數(shù)據(jù)在解密后,就不可能通過哈希。
比如說公鑰就是之前的例子 Hello,我們假設(shè)哈希算法是獲取字符串的最后一個(gè)字符,那么 Hello 的哈希值就是 o,所以加密字符串是 Ifmmpp。雖然公鑰已知,每個(gè)人都可以解密,解密完也可以篡改,但是因?yàn)闆]有私鑰, 所以無法正確的加密。所以它再返回給客戶端的數(shù)據(jù)是無效數(shù)據(jù),用公鑰解析后會(huì)得到亂碼。即使攻擊者通過多次嘗試碰巧能夠解析,也無法通過哈希校驗(yàn)。
首先真正的服務(wù)器下發(fā)的內(nèi)容,無法被別人篡改。他們有權(quán)威機(jī)構(gòu)的公鑰,所以可以解密,但是因?yàn)闆]有私鑰,所以解密以后的信息無法加密。沒有加密或者錯(cuò)誤加密的信息被客戶端用公鑰解密以后,必然無法通過哈希校驗(yàn)。
但是,如果你一開始請(qǐng)求的就不是真的服務(wù)器,而是一個(gè)攻擊者,此時(shí)的他完全有機(jī)會(huì)進(jìn)行中間人攻擊。我們知道第一次握手的時(shí)候服務(wù)器會(huì)下發(fā)用于證明自己身份的證書,這個(gè)證書會(huì)用預(yù)設(shè)在設(shè)備上的公鑰來解密。所以要么是經(jīng)過認(rèn)證的證書用權(quán)威機(jī)構(gòu)的私鑰加密,再用權(quán)威機(jī)構(gòu)解密,要么是用非權(quán)威機(jī)構(gòu)的私鑰加密,然后找不到公鑰解密。
所以如果不小心安裝過非權(quán)威機(jī)構(gòu)的根證書,比如黑客提供的惡意證書,這時(shí)候設(shè)備上就多了一個(gè)預(yù)設(shè)的公鑰,那么用惡意私鑰加密的證書就能被正常解析出來。所以千萬不要隨便裝根證書,這等于是為那些惡意證書留了一扇門。
當(dāng)然,凡是都有兩面性。我們知道 Charles 可以調(diào)試 HTTPS 通信,它的原理就是需要用戶安裝 Charles 的根證書,然后我們的請(qǐng)求會(huì)被代理到 Charles 服務(wù)器,它下發(fā)的 Charles 證書才能被正確解析。另一方面,Charles 會(huì)作為客戶端,從真正的服務(wù)器哪里拿到正確的 https 證書并用于后續(xù)通信。幸好 Charles 不是流氓軟件,或者它的私鑰一旦泄露,對(duì)用戶都會(huì)造成很大的影響。
我可以舉一個(gè)例子,證書有多個(gè)種類,最貴的叫 EV (Extended Validation),它需要公司營業(yè)執(zhí)照等多個(gè)文件才能申請(qǐng)人工審核,好處也很明顯,可以在瀏覽器地址欄左側(cè)準(zhǔn)確顯示公司名稱,比如 Bitbucket 的官網(wǎng):
代理模式下無法顯示
TCP 有三次握手,再加上 HTTPS 的四次握手,會(huì)不會(huì)影響性能?
首先,HTTPS 肯定會(huì)更慢一點(diǎn),時(shí)間主要花費(fèi)在兩組 SSL 之間的耗時(shí)和證書的讀取驗(yàn)證上,對(duì)稱算法的加解密時(shí)間幾乎可以忽略不計(jì)。
而且如果不是首次握手,后續(xù)的請(qǐng)求并不需要完整的握手過程??蛻舳丝梢园焉洗蔚募用芮闆r直接發(fā)送給服務(wù)器從而快速恢復(fù),具體細(xì)節(jié)可以參考 圖解SSL/TLS協(xié)議。
除此以外,SSL 握手的時(shí)間并不是只能用來傳遞加密信息,還可以承擔(dān)起客戶端和服務(wù)器溝通 HTTP2 兼容情況的任務(wù)。因此從 HTTPS 切換到 HTTP2.0 不會(huì)有任何性能上的開銷,反倒是得益于 HTTP2.0 的多路復(fù)用等技術(shù),后續(xù)可以節(jié)約大量時(shí)間。
如果把 HTTPS2.0 當(dāng)做目標(biāo),那么 HTTPS 的性能損耗就更小了,遠(yuǎn)遠(yuǎn)比不上它帶來的安全性提升。
相信以上九個(gè)問題足夠幫助新人了解 HTTPS 了,但這只是基本概念,關(guān)于 HTTPS 的使用(比如 iOS 上的一些具體問題)還需要不斷嘗試和研究。
本文來自于簡(jiǎn)書
鏈接:www.jianshu.com/p/072a657337ae