引言
為什么把這個作為選題。
大概也是2年前,我的同事,在面試某大廠遇到的問題與我一起探討。這個時候我發(fā)現(xiàn),雖然TLS(https)這個東西大部分時候可能不會被直接用到,但很容易被作為考察的目標(biāo)范圍。同時這方面的認(rèn)知不同的人很容易出現(xiàn)不同的偏差。
問題內(nèi)容概括來說就是URI/URL部分在https中是否會被加密。面試官認(rèn)為url在https里是不會被加密的,這與事實是有偏差的(最開始只是知道他這里是有誤的,沒有思考這個地方之所以容易被誤解的原因),后面會提到,為什么這個點容易出現(xiàn)理解偏差。
下文將著重分析說明HTTPS的安全性是如何被保證的。(本文會盡量避免直接引用名詞含義解釋,在說明過程中會重點描述協(xié)議與當(dāng)前內(nèi)容有直接相關(guān)的特性,部分內(nèi)容會引用作者之前寫的帖子或評論)
HTTPS用什么來保障傳輸安全
結(jié)論還是很簡單的:我們說https的安全性是由TLS保障的
先問是不是,再問為什么!
HTTP與TLS
這張圖展示了http各版本店基本數(shù)據(jù)傳輸結(jié)構(gòu)。*(該圖引至bagder)*
從HTTP 1 開始http就在利用TLS確保其安全性(事實上http 0.9就開始在使用SSL)。無論HTTP如何升級,承載其安全特性的組件TLS的地位始終沒有被動搖。(從1995年TLS3 首次部署到現(xiàn)在已經(jīng)超過20年)
值得一提的是作為最知名的傳輸層協(xié)議TCP,HTTP也計劃在HTTP3中將其替換,不過其依然沿用最新版本的TLS保障其安全 (舉這個例子并不是說TCP不優(yōu)秀)
上圖時間線簡單展示了HTTP及SSL/TLS的關(guān)鍵時間線(http1.1 在1999年時有一次定稿,有的資料上會認(rèn)為1999年是http1.1正式發(fā)布的時間點)。不難發(fā)現(xiàn)2者的發(fā)展一直保持微妙的同步,當(dāng)然這與web爆發(fā)發(fā)展有關(guān)系,http最知名的版本http1.1 及 現(xiàn)在TLS的基礎(chǔ)版本SSL 3 都出現(xiàn)在1996年前后,其影響也一直持續(xù)到了現(xiàn)在。
20年前的基礎(chǔ)
數(shù)據(jù)來源 :https://almanac.httparchive.org/en/2021/http
上圖是http各版本當(dāng)前在web系統(tǒng)中的使用占比,不難看出 http 1.1 至今仍然被廣泛使用,這個數(shù)字在2020年甚至還有50% (雖然統(tǒng)計中HTTP 2+ 超過了7成,但是并不代表這7成服務(wù)不支持HTTP 1.1,他們中大部分可以自動協(xié)商降級支持1.1)
而1996年被重新設(shè)計的SSL3.0 也一直延用至今(1999年發(fā)布的TLS1.0與SSL3.0 修改不大,以至于后面有的地方認(rèn)為他們是同一個版本)
PS :HTTP與TSL是完全2個獨立的協(xié)議,只是HTTPS利用TLS保證其安全性。
TLS其他應(yīng)用范圍
當(dāng)然不能因為http一直與tls綁定,我們就相信tls在安全方面的能力。 (畢竟大家平時在引入三方資源時都會先確認(rèn)用“他”的人多不多,大部分會優(yōu)先信任被廣泛使用的資源)
我們常用的SSH利用TLS保證連接的安全性,http的好朋友Websocket也在使用TLS,我們常見的VPN也在使用TLS確保我們的隱私安全。
這些基礎(chǔ)事實是大家對TLS的認(rèn)可,同時也表明TLS在安全傳輸方面的事實地位。
HTTPS/TLS如何確保數(shù)據(jù)傳輸安全
那TLS是如何保證其安全的,為什么其地位20多年都無法被撼動。
密鑰交換
數(shù)據(jù)如何安全傳輸,當(dāng)然第一時間就能想到“數(shù)據(jù)加密”(不過數(shù)據(jù)的傳輸安全遠(yuǎn)不僅如此,除了機(jī)密性,還需要有鑒別,數(shù)據(jù)完整性,和不可抵賴性,這些特性TLS都可以做到,不過不在本文討論范圍)
雖然簡單加密是不夠的,不過消息加密確實一切的基礎(chǔ)。看起來并不難,服務(wù)器與客戶端只需要有一個只有他們2方才知道的密鑰,如何用這個密鑰傳輸數(shù)據(jù)就可以了。
現(xiàn)在真正的問題來了,這個密鑰要怎么才能做的只有客戶端與服務(wù)器才知道,我們知道在互聯(lián)網(wǎng)上任何數(shù)據(jù)包的傳輸都需要經(jīng)過許許多多路由器等網(wǎng)絡(luò)設(shè)備,其中任意一臺設(shè)備都知道你的數(shù)據(jù)包里是什么內(nèi)容,我們不可能通過網(wǎng)絡(luò)直接把這個密鑰發(fā)送給對方。
有一個方案其實很常見,密鑰離線分發(fā)。比如常見的U盾,口令卡,銀行系統(tǒng)用的分量密鑰卡等等都是用的類似離線的手段保證密鑰的安全。這種密鑰交換的方式的確是安全了不過代價太大,對于廣泛應(yīng)用與互聯(lián)網(wǎng)的http顯然不合適。
公開密鑰算法
不過幸好早在上個世紀(jì)70年年代就出現(xiàn)了公開的非對稱加密算法(公開密鑰算法,個人覺得這個名字更能體現(xiàn)這個密鑰算法的特點),而且其安全性到現(xiàn)如今依然被證明有效(這也是為什么1995就已經(jīng)問世的SSL3 可以作為TLS的基礎(chǔ)一直延用至今的原因),借助于公開密鑰算法使得密鑰在客戶端于服務(wù)器之間的安全傳播成為可能。
TLS支持的密鑰交換算法有許多(比如RSA密鑰交換,Diffie-Hellman密鑰交換.......)。我們看下RAS密碼交換(因為他被廣泛應(yīng)用,且相對簡單),看他是如何保證密鑰交換的安全性的。
先介紹非對稱加密算法的一個重要特點,加密時需要用到一對密鑰(公鑰,私鑰),公鑰加密的數(shù)據(jù)只能通過私鑰解密,私鑰加密的數(shù)據(jù)只能通過公鑰解密。
- 通常我們說的對稱加密基本上都是簡單異或或異或的簡單變種操作,這正好是計算機(jī)擅長的,所以速度非常快。(一般密鑰實際上只是一種二進(jìn)制數(shù)據(jù)塊)
- 非對稱加密算法是用的數(shù)學(xué)算法,無論是加解密,還是密鑰對的生成消耗都比對稱加密慢很多。(密鑰實際上是一個數(shù)字,很大的數(shù)字)
密鑰如何交換
前面我們已經(jīng)提到了工作密鑰是不可以直接在網(wǎng)絡(luò)上傳播的,既然密鑰不能中網(wǎng)絡(luò)中直接傳播,那我們能不能把密鑰加密后傳輸呢?非對稱加密算法與這個需求完美契合。
服務(wù)端可以先將公鑰直接發(fā)送給客戶端,然后客戶端自己生成一個隨機(jī)密鑰(TLS里這里交換的其實是預(yù)主密鑰),然后使用公開的公鑰加密這個密鑰發(fā)送給服務(wù)器,因為私鑰只有服務(wù)器知道,所以只有服務(wù)器才能解密這個密鑰。這樣一來就出現(xiàn)了一個只有客戶端和服務(wù)器才知道的預(yù)主密鑰,然后通過這個預(yù)主密鑰可以生成主密鑰,再最終生成工作密鑰。
上圖簡單概括了預(yù)主密鑰傳輸過程(其實就是TLS握手的其中一部分)
中間人攻擊
看起來是不是很完美,就算密鑰交換過程中的數(shù)據(jù)被其他人知道也沒有關(guān)系,因為他們沒有私鑰,沒有辦法解密,不過還是有漏洞,你連接的網(wǎng)絡(luò)設(shè)備可不是只能看你的數(shù)據(jù),他還可以任意截斷修改你的原始報文,這就是中間人攻擊。
雖然客戶端可以使用公鑰加密預(yù)主密鑰,不過客戶端的公鑰是從哪里來的呢,其實也還是通過網(wǎng)絡(luò)由服務(wù)器下發(fā)給客戶端的。那既然也是通過網(wǎng)絡(luò),在下發(fā)公鑰的時候工作密鑰可還沒有生成,這就是說公鑰可以被網(wǎng)絡(luò)中的第三方截獲然后替換,客戶端以為收到的是服務(wù)器的公鑰,而實際上收到的是中間人自己生成的公鑰(中間人知道與之對應(yīng)的私鑰),這樣一來客戶端就會在毫不知情的情況下與中間人完成密鑰交換(TLS握手),然后中間人會代替客戶端與服務(wù)端交互,用戶及服務(wù)端都不知道有中間人的操作,數(shù)據(jù)就會完全暴露給攻擊者。
證書驗證
公鑰基礎(chǔ)設(shè)施
現(xiàn)在問題就變成了客戶端如何確認(rèn)自己收到的公鑰不是任何攻擊者的證書。PKI(公鑰基礎(chǔ)設(shè)施)完美的解決了這個問題。
其實之前就有提到過當(dāng)前最安全的手段其實就是密鑰離線分發(fā),而整個web系統(tǒng)網(wǎng)站這么多不太可能每個網(wǎng)站每個服務(wù)器都來給網(wǎng)站離線下發(fā)密鑰,這個時候就需要一個中間商,一個大家都認(rèn)可的中間商CA中心(證書簽發(fā)機(jī)構(gòu))來幫我們完成服務(wù)端公鑰的驗證,雖然為每個網(wǎng)站離線分發(fā)公鑰不太可能,不過我們可以提前為客戶端離線分發(fā)受信任的根證書,利用這個根證書去驗證網(wǎng)站服務(wù)端發(fā)客戶端的公鑰,這就是前面提到的PKI。
CA中心會提前將自己的根證書加入到操作系統(tǒng)的根證書列表(系統(tǒng)安裝的時候就在那里了),許多瀏覽器也有自己受信根證書列表,這些證書都是內(nèi)置的,網(wǎng)絡(luò)嗅探者無法污染這些根證書。
那操作系統(tǒng)憑什么又如何要信任這些根證書呢? 這個就很直白了,剛剛說了是“權(quán)威”機(jī)構(gòu)的根證書,你可以不信任,不過基于PKI的證書校驗將無法運作,當(dāng)然這些權(quán)威的證書頒發(fā)機(jī)構(gòu)也也確實要能對得起他的權(quán)威。
現(xiàn)在客戶端已經(jīng)有了離線的信任根證書,那他是如何認(rèn)證網(wǎng)站發(fā)過來的公鑰呢(網(wǎng)站發(fā)過來實際上是證書,這個證書里包含公鑰)
證書驗證過程
client會校驗證書的合法性,并根據(jù)驗證結(jié)果決定是否連接服務(wù)器。(本節(jié)內(nèi)容yin yo)
如上圖在瀏覽器中任意找一個https的網(wǎng)頁,服務(wù)器在建立TLS連接前都會先將自己的公鑰證書發(fā)給客戶端,我們查看其證書信息。
從這里面我們能看到證書包含以下內(nèi)容:
(1) Validity也即有效期,有效期包含生效時間和失效時間,是一個時間區(qū)間;
(2) 公鑰信息Subject Public Key Info,包括公鑰的加密算法和公鑰內(nèi)容;
(3) 指紋信息,指紋用于驗證證書的完整性,也是證書校驗的關(guān)鍵,他確保證書沒有被修改過。 其原理就是在頒發(fā)證書時,頒發(fā)者根據(jù)指紋算法(單向散列函數(shù))(此處證書使用了SHA-1和SHA-256算法 有多個指紋是為了兼容老的客戶端)計算整個證書的hash指紋【證書內(nèi)容hash值使用CA私鑰加密就是指紋】并和證書放在一起,client在打開證書時,自己也根據(jù)指紋算法計算一下證書的hash值,同時使用自己信任的根證書的公鑰解密hash指紋計算出原始hash,如果hash值不一致,則表明證書內(nèi)容被篡改過;
(4) 證書的簽名Certificate Signature Value和Certificate Signature Algorithm,對證書簽名所使用的Hash算法和Hash值;
(5) 簽發(fā)該證書的CA機(jī)構(gòu)Issuer;
(6) 該證書是簽發(fā)給哪個組織/公司信息Subject;
(7) 證書版本Version、證書序列號Serial Number以及Extensions擴(kuò)展信息等。
上圖即是證書指紋校驗的主要過程,不難看出Client校驗證書的核心其實是CA公鑰解密出原始指紋。那這個CA公鑰從哪里來,這就是上文中提到的系統(tǒng)根證書。
這里就有一個關(guān)鍵點證書的頒發(fā),我們現(xiàn)在知道根證書里的公鑰是用來解密網(wǎng)站公鑰證書的指紋的,為了確保安全系統(tǒng)會有一批自己信任的CA公鑰列表(根證書),操作系統(tǒng)會提前內(nèi)置好這些CA的根證書。這些根證書為什么可以驗證網(wǎng)站的證書呢 ,因為網(wǎng)址的證書也是這些CA機(jī)構(gòu)簽發(fā)的。CA對應(yīng)的一般是權(quán)威機(jī)構(gòu)或組織,然后由這些權(quán)威機(jī)構(gòu)頒發(fā)證書時使用他們自己的私鑰去簽名(為證書生成指紋)然后再頒發(fā)給網(wǎng)站,這樣就確保了只有權(quán)威機(jī)構(gòu)頒發(fā)給各個網(wǎng)站的證書才會被客戶端校驗通過。
網(wǎng)站證書的頒發(fā)
順便我們看一下CA頒發(fā)給網(wǎng)站的證書具體是怎樣的,一般有2部分組成
公鑰證書:這個就是網(wǎng)站后面會公開發(fā)送給客戶端的證書 (CA的私鑰只會用來給這個證書簽名,不關(guān)心證書里的密鑰)
私鑰文件:里面只有一個私鑰(與公鑰證書里公鑰是一對,用來在TLS握手只解密預(yù)主密鑰)
如上圖sipv4.com.key就是私鑰文件,sipv4.com.cer就是公鑰證書 (如果看的細(xì),會發(fā)現(xiàn)cer里不止含有一個CERTIFICATE,其實他是一個證書鏈)
上圖簡單描述了證書如何在TLS里發(fā)揮作用。有一點需要注意,CA再為網(wǎng)站頒發(fā)證書時會驗證申請者是網(wǎng)站的擁有者,這樣可以確保只有網(wǎng)站的擁有者才可能擁有合法的證書。這一通操作下來即使中間人用自己生成的公鑰證書來欺騙客戶端時,客戶端也能馬上反應(yīng)過來從而中止鏈接。
現(xiàn)在我們再來看下攻擊者的處境,攻擊者如果偽裝成網(wǎng)站A,握手時攻擊者需要給用戶發(fā)送公鑰證書,攻擊者有2個選擇。
- 發(fā)送真正的證書(因為公鑰證書是公開的,任何人都可以方便的獲取),這樣雖然可以通過客戶端的證書校驗,不過攻擊者因為沒有私鑰,無法解密客戶端發(fā)過來的預(yù)主密鑰,握手會最終失敗。
- 發(fā)送攻擊者自己生成的公鑰證書,這時雖然攻擊者有對應(yīng)的私鑰,不過因為自己生成的證書沒有CA的簽名,無法通過客戶端的證書驗證,握手也會被終止。
這樣一來密鑰的交換,交換過程的安全就都得到了保障。
結(jié)束
url加密
現(xiàn)在回到開頭,為什么有些同學(xué)會認(rèn)為https不會加密URL。前面講到的在密鑰交換完成前數(shù)據(jù)流其實是明文,也就是說網(wǎng)站公鑰證書的傳輸是以明文的形式進(jìn)行的,上面也提到了證書里是包含Subject,而這個信息里往往有目標(biāo)網(wǎng)站的域名,所以如果直接查看未解密的https流量,往往是可以看到域名的明文信息的,這個信息很有可能讓人誤以為這是url信息
為什么不使用公鑰加密數(shù)據(jù)
還有一個問題也會經(jīng)常會被提到,TLS為什么不使用公鑰直接加密數(shù)據(jù),這個問題也與開頭的問題一樣,很容易有認(rèn)知上的偏差
看了很多被廣泛接受的答案都是“性能”問題,我很早之前也是這么認(rèn)為的,不過現(xiàn)在我知道“性能”問題相對于安全性上是否可行那就根本不是問題,不能使用公鑰加密是因為安全上根本不可行,會讓TLS形同虛設(shè)!
隨便打開一個https網(wǎng)站的證書,不同電腦不同時間獲取的證書里的公鑰其實都是一樣的,也就是說這個公鑰是公開的而且任何人都知道,那就不可能自己用公鑰去加解密。這樣服務(wù)器返回的數(shù)據(jù)那不是任何人都能解密了
如上圖任何人都知道baidu的公鑰,任何人也都能解密baidu返回給客戶端的數(shù)據(jù)。
當(dāng)然TLS的握手是個十分嚴(yán)謹(jǐn)及復(fù)雜的過程,他還有很多認(rèn)證的功能在里面,如果直接用公鑰加密數(shù)據(jù)了那就拋棄了握手里面的很多功能,這里就不展開了。(因為就上面提到的所有返回數(shù)據(jù)都能被任何人解密那就是致命問題了,相比之下其他的問題都是小問題)
關(guān)于非對稱加密算法應(yīng)該加密什么數(shù)據(jù)
而不用公鑰加密數(shù)據(jù)本身這是個策略,不僅僅是TLS 這些,絕大部分加密系統(tǒng)都是使用的這個策略,因為非對稱加密加密的內(nèi)容本質(zhì)其實是數(shù)字(可以想象把1kb的數(shù)據(jù)轉(zhuǎn)換成數(shù)字 會是個什么情景,當(dāng)然他也不會允許你加密這么大的數(shù)據(jù),還要特殊處理),并且還是數(shù)學(xué)運算,計算機(jī)處理起來會很慢(很多銀行機(jī)構(gòu)為了提高速度還會使用特殊的加密設(shè)備加密機(jī)/卡這類東西)。可以看到非對稱算法天生就不是為加密長度不可控的數(shù)據(jù)設(shè)計的,他往往用來加密長度有限的關(guān)鍵數(shù)據(jù),比如數(shù)據(jù)的hash值。而DES、AES這種對稱算法就不一樣,他們加密主要靠異或跟置換,大數(shù)據(jù)直接分組 ,這些操作計算機(jī)天生就很在行速度很快,他們對加密這些任意長度的數(shù)據(jù)流就很合適。
總結(jié):
絕大部分加密系統(tǒng)都不會用非對稱算法直接加解密數(shù)據(jù)(因為就不是為這種場景設(shè)計的)
而TLS就更不可能用公鑰加密數(shù)據(jù)(因為除了上面提到的設(shè)計上的不合理,這種操作還讓服務(wù)返回的數(shù)據(jù)失去了任何保護(hù)能力)
TLS地位為什么難以被動搖
是不是有必要,作為其基礎(chǔ)的非對稱加密算法目前為止依然十分十分可靠,而已也找不到更加合適的替代方案。
與其有直接關(guān)系的PKI體系已經(jīng)形成,已經(jīng)遍布全球CA中心并不是這么容易建立,因為需要大家互相信任,要推翻這個體系也并不容易。
來源:
https://www.cnblogs.com/lulianqi/p/16476166.html