本文首發(fā)于我的個(gè)人技術(shù)博客看完還不懂HTTPS我直播吃翔
存在即合理
http是非常常見的應(yīng)用層協(xié)議辣卒,是超文本傳輸協(xié)議的簡(jiǎn)稱掷贾,其傳輸?shù)膬?nèi)容都是明文的。在這個(gè)混亂的世界荣茫,明文傳輸信息想想就可怕想帅,網(wǎng)絡(luò)“小混混”的手段遠(yuǎn)比我們這些凡人高明得多,他們有一萬種方式劫持啡莉,篡改我們的數(shù)據(jù)港准。對(duì)于一個(gè)網(wǎng)站或者服務(wù),如果你給你的用戶兩個(gè)選擇:
- 通訊數(shù)據(jù)明文傳輸咧欣,速度快浅缸;
- 通訊數(shù)據(jù)加密傳輸,但是速度可能會(huì)稍微慢一點(diǎn).
我想魄咕,只要腦袋沒有長(zhǎng)歪的用戶都寧愿犧牲一點(diǎn)速度去換取數(shù)據(jù)傳輸?shù)陌踩?/p>
這樣衩椒,https的存在就具備了合理性,https中的s表示SSL或者TLS哮兰,就是在原h(huán)ttp的基礎(chǔ)上加上一層用于數(shù)據(jù)加密毛萌、解密、身份認(rèn)證的安全層奠蹬。
一層層揭開HTTPS神秘面紗
本文試圖通過層層漸進(jìn)方式來通俗的闡述https的原理朝聋,若有錯(cuò)誤,歡迎大家指正囤躁。
雖然要層層漸進(jìn),但是我們不妨先奉上剛畫好的還熱乎著的https通信完整流程圖:
從上圖可以看到荔睹,右邊有一堆鑰匙狸演,一看到鑰匙我們就能想到這個(gè)過程免不了加密。另外僻他,那些鑰匙長(zhǎng)得還不一樣宵距,有些只有一把,有些是一對(duì)吨拗,嗯满哪,是的,你看得真仔細(xì)劝篷。
好的哨鸭,扯遠(yuǎn)了,現(xiàn)在開始層層漸進(jìn)娇妓。
第一層(安全傳輸數(shù)據(jù))
假如我們要實(shí)現(xiàn)一個(gè)功能:一個(gè)用戶A給一個(gè)用戶B發(fā)消息像鸡,但是要保證這個(gè)消息的內(nèi)容只能被A和B知道,其他的無論是墨淵上神還是太上老君都沒辦法破解或者篡改消息的內(nèi)容哈恰。
如上圖只估,需求就是這么簡(jiǎn)單志群,A給B發(fā)一條消息,因?yàn)楸容^私密蛔钙,不想被其他人看到锌云。
由于消息不想被其他人看到,所以我們自然而然就會(huì)想到為消息加密吁脱,并且只有A和B才有解密的密鑰宾抓。這里需要考慮幾點(diǎn):
- 使用什么加密方式?
- 密鑰怎么告知對(duì)方豫喧?
對(duì)于第一個(gè)問題石洗,加密算法分為兩類:對(duì)稱加密和非對(duì)稱加密,這里我們選擇對(duì)稱機(jī)密紧显,原因有如下幾個(gè):
- 對(duì)稱加密速度快讲衫,加密時(shí)CPU資源消耗少;
- 非對(duì)稱加密對(duì)待加密的數(shù)據(jù)的長(zhǎng)度有比較嚴(yán)格的要求孵班,不能太長(zhǎng)涉兽,但是實(shí)際中消息可能會(huì)很長(zhǎng)(比如你給你女朋友發(fā)情書),因此非對(duì)稱加密就滿足不了篙程;
對(duì)于第二個(gè)問題枷畏,這是導(dǎo)致整個(gè)https通信過程很復(fù)雜的根本原因。
如果A或B直接把他們之間用于解密的密鑰通過互聯(lián)網(wǎng)傳輸給對(duì)方虱饿,那一旦密鑰被第三者劫持拥诡,第三者就能正確解密A,B之間的通信數(shù)據(jù)。
第二層(安全傳輸密鑰)
通過第一層的描述氮发,第二層需要解決的問題是:安全地傳輸A,B之間用于解密數(shù)據(jù)的密鑰渴肉。
因?yàn)槿绻麄鬏斶^程中這把密鑰被第三者拿到了,就能解密傳通信數(shù)據(jù)爽冕,所以仇祭,這把密鑰必須得加密,就算第三者劫持到這把加密過的密鑰颈畸,他也不能解密乌奇,得到真正的密鑰。
這里有一個(gè)問題眯娱,那要用什么方式加密這把密鑰呢礁苗?如果使用對(duì)稱加密,那這個(gè)對(duì)稱加密的密鑰又怎么安全地告訴對(duì)方呢困乒?完了寂屏,陷入死循環(huán)了.... 所以,一定不能用對(duì)稱加密
那就是用非對(duì)稱加密咯,那如何應(yīng)用非對(duì)稱加密來加密那把密鑰呢迁霎?
考慮如下方式:
- 客戶端: 我要發(fā)起HTTPS請(qǐng)求吱抚,麻煩給我一個(gè)非對(duì)稱加密的公鑰;
- 服務(wù)器: (生成一對(duì)非對(duì)稱加密的密鑰對(duì)考廉,然后把公鑰發(fā)給客戶端)秘豹,接著,這是公鑰昌粤;
- 客戶端:(收到公鑰既绕,生成一個(gè)隨機(jī)數(shù),作為上圖中那一把密鑰涮坐,用剛才收到的公鑰加密這個(gè)密鑰凄贩,然后發(fā)給服務(wù)器)這是我剛生成的加密過的密鑰;
- 服務(wù)器:(收到加密后的密鑰袱讹,用本地的第一步自己生成的非對(duì)稱加密的私鑰解密疲扎,得到真正的密鑰);
- 現(xiàn)在,客戶端和服務(wù)器都知道了這把密鑰捷雕,就能愉快地用這個(gè)密鑰對(duì)稱加密數(shù)據(jù)...
分析一下上面步驟的可行性:
- 上述步驟中最終用于加密數(shù)據(jù)的密鑰是客戶端生成并且用公鑰加密之后傳給服務(wù)器的椒丧,因?yàn)樗借€只有服務(wù)器才有,所以也就只有服務(wù)器才能解開客戶端上報(bào)的密鑰救巷;
- 要保證傳輸?shù)拿荑€只能被服務(wù)器解密壶熏,就得保證用于加密密鑰的公鑰一定是服務(wù)器下發(fā)的,絕對(duì)不可能被第三方篡改過浦译;
因?yàn)檫€可能存在一種"中間人攻擊"的情況棒假,如下圖:
感謝XngPro的指正,上圖第7步管怠,應(yīng)該是『壞人用B私鑰解密得到K淆衷,然后使用A公鑰加密發(fā)給服務(wù)器』
這種情況下,客戶端和服務(wù)器之間通信的數(shù)據(jù)就完全被壞人破解了渤弛。
第三層(安全傳輸公鑰)
從上一層可以知道,要保證數(shù)據(jù)的安全甚带,就必須得保證服務(wù)器給客戶端下發(fā)的公鑰是真正的公鑰她肯,而不是中間人偽造的公鑰。那怎么保證呢鹰贵?
那就得引入數(shù)字證書了晴氨,數(shù)字證書是服務(wù)器主動(dòng)去權(quán)威機(jī)構(gòu)申請(qǐng)的,證書中包含了上一個(gè)圖中的加密過的A公鑰和權(quán)威機(jī)構(gòu)的信息碉输,所以服務(wù)器只需要給客戶端下發(fā)數(shù)字證書即可∽亚埃現(xiàn)在流程圖如下:
那數(shù)字證書中的A公鑰是如何加密的呢?
答案是非對(duì)稱加密,只不過這里是使用只有權(quán)威機(jī)構(gòu)自己才有的私鑰加密枝哄。
等一下肄梨,既然A公鑰被權(quán)威機(jī)構(gòu)的私鑰加密了,那客戶端收到證書之后怎么解密證書中的A公鑰呢?需要有權(quán)威機(jī)構(gòu)的公鑰才能解密澳幼丁众羡!那這個(gè)權(quán)威機(jī)構(gòu)的公鑰又是怎么安全地傳輸給客戶端的呢?感覺進(jìn)入了雞生蛋蓖租,蛋生雞的悖論了~~
別慌粱侣,答案是權(quán)威機(jī)構(gòu)的公鑰不需要傳輸,因?yàn)闄?quán)威機(jī)構(gòu)會(huì)和主流的瀏覽器或操作系統(tǒng)合作蓖宦,將他們的公鑰內(nèi)置在瀏覽器或操作系統(tǒng)環(huán)境中齐婴。客戶端收到證書之后,只需要從證書中找到權(quán)威機(jī)構(gòu)的信息稠茂,并從本地環(huán)境中找到權(quán)威機(jī)構(gòu)的公鑰柠偶,就能正確解密A公鑰。
這樣就絕對(duì)安全了嗎主慰?既然權(quán)威技能能給服務(wù)器簽發(fā)數(shù)字證書嚣州,那為什么就不可能給中間人簽發(fā)數(shù)字證書呢?畢竟賺錢的生意權(quán)威機(jī)構(gòu)也不會(huì)拒絕的呀。
試想一下:
服務(wù)器給客戶端下發(fā)數(shù)字證書時(shí)證書被中間人劫持了共螺,中間人將服務(wù)器的證書替換成自己的證書下發(fā)給客戶端该肴,客戶端收到之后能夠通過權(quán)威機(jī)構(gòu)的公鑰解密證書內(nèi)容(因?yàn)橹虚g人的證書也是權(quán)威機(jī)構(gòu)私鑰加密的),從而獲取公鑰藐不,但是匀哄,這里的公鑰并不是服務(wù)器原本的A公鑰,而是中間人自己證書中的B公鑰雏蛮。從第二層可知涎嚼,如果不能保證客戶端收到的公鑰是服務(wù)器下發(fā)的,那整個(gè)通信數(shù)據(jù)的安全就沒法保證挑秉。簡(jiǎn)單總結(jié)就是證書被調(diào)包~
所以法梯,還得保證客戶端收到的證書就是服務(wù)器下發(fā)的證書,沒有被中間人篡改過犀概。
第四層(安全傳輸證書)
這一層立哑,我們的任務(wù)是:保證客戶端收到的證書是服務(wù)器下發(fā)的證書,沒有被中間人篡改過姻灶。
所以铛绰,這里就有兩個(gè)需求:
- 證明證書內(nèi)容沒有被第三方篡改過;
- 證明證書是服務(wù)器下發(fā)的产喉;
其實(shí)這些問題捂掰,數(shù)字證書本身已經(jīng)提供方案了敢会,數(shù)字證書中除了包含加密之后的服務(wù)器公鑰,權(quán)威機(jī)構(gòu)的信息之外这嚣,還包含了證書內(nèi)容的簽名(先通過Hash函數(shù)計(jì)算得到證書數(shù)字摘要鸥昏,然后用權(quán)威機(jī)構(gòu)私鑰加密數(shù)字摘要得到數(shù)字簽名),簽名計(jì)算方法以及證書對(duì)應(yīng)的域名疤苹。這樣一來互广,客戶端收到證書之后:
- 使用權(quán)威機(jī)構(gòu)的公鑰解密數(shù)字證書,得到證書內(nèi)容(服務(wù)器的公鑰)以及證書的數(shù)字簽名卧土,然后根據(jù)證書上描述的計(jì)算證書簽名的方法計(jì)算一下當(dāng)前證書的簽名惫皱,與收到的簽名作對(duì)比,如果一樣尤莺,表示證書一定是服務(wù)器下發(fā)的旅敷,沒有被中間人篡改過。因?yàn)橹虚g人雖然有權(quán)威機(jī)構(gòu)的公鑰颤霎,能夠解析證書內(nèi)容并篡改媳谁,但是篡改完成之后中間人需要將證書重新加密,但是中間人沒有權(quán)威機(jī)構(gòu)的私鑰友酱,無法加密晴音,強(qiáng)行加密只會(huì)導(dǎo)致客戶端無法解密,如果中間人強(qiáng)行亂修改證書缔杉,就會(huì)導(dǎo)致證書內(nèi)容和證書簽名不匹配锤躁。所以證書簽名就能判斷證書是否被篡改
- 再考慮證書被掉包的情況:中間人同樣可以向權(quán)威機(jī)構(gòu)申請(qǐng)一份證書,然后在服務(wù)器給客戶端下發(fā)證書的時(shí)候劫持原證書或详,將自己的假證書下發(fā)給客戶端系羞,客戶端收到之后依然能夠使用權(quán)威機(jī)構(gòu)的公鑰解密證書,并且證書簽名也沒問題霸琴。但是這個(gè)時(shí)候客戶端還需要檢查證書中的域名和當(dāng)前訪問的域名是否一致椒振。如果不一致,會(huì)發(fā)出警告梧乘!
從上面的分析可以看到澎迎,數(shù)字證書中的信息確實(shí)能讓客戶端辨別證書的真?zhèn)巍?/p>
怎么樣?經(jīng)過這么幾句通俗的話选调,是不是對(duì)HTTPS的通信機(jī)制有了比較清晰的認(rèn)識(shí)了嗡善。當(dāng)然了,有一些可能是我胡扯的学歧,不一定對(duì),大家多多指正各吨!