前情提要
上一篇文章簡(jiǎn)單描述了加密解密的演進(jìn)歷史,如果對(duì)這部分不感興趣的小伙伴其實(shí)可以跳過(guò)那篇文章,不過(guò)在講之前我還是要先做一些知識(shí)點(diǎn)鋪墊工作,避免文中遇到這些名詞時(shí)沒(méi)頭緒。
加密主要是分成對(duì)稱(chēng)加密和非對(duì)稱(chēng)加密,這里會(huì)涉及到這些知識(shí)點(diǎn):
- 鑰匙,可以理解為原文密文的對(duì)應(yīng)替換規(guī)則;
- 對(duì)稱(chēng)加密,指的是加密和解密過(guò)程中使用的鑰匙都是同一把鑰匙,這樣雖然加密解密后信息安全傳輸?shù)玫奖U?,但是存在一個(gè)嚴(yán)重問(wèn)題就是對(duì)稱(chēng)加密使用到的鑰匙要如何傳遞給對(duì)方;
- 非對(duì)稱(chēng)加密,指的是加密和解密過(guò)程需要使用到的鑰匙是兩把不同的鑰匙,公開(kāi)的那把被稱(chēng)為公鑰,自己持有那把被稱(chēng)為私鑰,所以我只需要將公鑰開(kāi)放出去,別人通過(guò)使用我的公鑰對(duì)信息進(jìn)行加密,等我收到消息時(shí)再用自己的私鑰進(jìn)行解密,這樣我就可以看到原文內(nèi)容了,這個(gè)過(guò)程既完成了信息安全傳輸,而且還避免了對(duì)稱(chēng)加密那把鑰匙傳輸?shù)膯?wèn)題;
- 簽名,非對(duì)稱(chēng)加密不僅可以公鑰加密私鑰解密,還可以私鑰加密公鑰解密,不過(guò)由于這個(gè)私鑰只有自己持有,所以這個(gè)過(guò)程也叫簽名,而公鑰解私鑰的過(guò)程也被稱(chēng)為驗(yàn)簽,為什么叫簽名呢,其實(shí)是因?yàn)樗借€只有我自己持有,所以可以利用這個(gè)特性對(duì)你進(jìn)行身份認(rèn)證的,就像是我給你寫(xiě)了張欠條然后簽了自己的名字,因?yàn)楣P跡并不是那么容易偽造的,而不可偽造也就可以用來(lái)進(jìn)行身份驗(yàn)證;
- 效率問(wèn)題,非對(duì)稱(chēng)加密由于涉及到大量數(shù)學(xué)運(yùn)算,所以加密解密效率相比對(duì)稱(chēng)加密是低的;
HTTPS 通信流程
講 HTTPS 之前我們先來(lái)看看為什么 HTTP 不能滿足我們的需求,它都存在哪些問(wèn)題?當(dāng)我們了解了它的缺點(diǎn),我們也就更容易理解,為什么 HTTPS 的通信過(guò)程要像現(xiàn)在這樣設(shè)計(jì)了。
HTTP 通信的四類(lèi)問(wèn)題
HTTP 通信的四類(lèi)問(wèn)題:
- 攔截(機(jī)密性),傳輸信息可以被中間人攔截,從而導(dǎo)致數(shù)據(jù)泄漏;
- 篡改(完整性),基于攔截,中間人可以對(duì)數(shù)據(jù)進(jìn)行了修改,從而沒(méi)辦法保證數(shù)據(jù)完整;
- 偽裝(身份驗(yàn)證),兩個(gè)人通信時(shí),任何一方都可能被中間人冒名頂替;
- 否認(rèn)(不可否認(rèn)),由于存在偽裝,所以其中一方可以假裝沒(méi)有收到對(duì)方消息或?qū)Ψ绞盏降南⒉皇亲约喊l(fā)的;
那我們能否利用已有知識(shí)解決這些問(wèn)題呢?答案是基本上可以,讓我們來(lái)看看這些問(wèn)題具體該如何解決:
- 機(jī)密性可以使用對(duì)稱(chēng)加密或非對(duì)稱(chēng)加密可以解決這個(gè)問(wèn)題,只是還有一些區(qū)別:
- 對(duì)稱(chēng)加密速度快效率高,非對(duì)稱(chēng)加密速度慢(因?yàn)樯婕暗酱罅繑?shù)據(jù)運(yùn)算)效率低;
- 對(duì)稱(chēng)加密雖然過(guò)程是安全的,但是信息加密傳輸之前的密鑰傳輸是一個(gè)很大的問(wèn)題;
- 完整性可以通過(guò)摘要算法來(lái)完成;
- 它會(huì)把任意長(zhǎng)度的數(shù)據(jù)壓縮成固定長(zhǎng)度,且生成的是獨(dú)一無(wú)二的摘要信息,就像指紋一樣;
- 會(huì)存在摘要信息沖突的可能性,所以要看具體摘要算法本身和信息長(zhǎng)度;
- 具有單向性(不可逆)和雪崩效應(yīng)(微小修改都會(huì)引起劇烈變化);
- 完整性還是要建立在機(jī)密性之上,因?yàn)槿绻畔⑹敲魑牡倪€是有可能被修改;
- 身份驗(yàn)證 / 不可否認(rèn):可以利用非對(duì)稱(chēng)加密的簽名特性來(lái)同時(shí)完成,這里還有知識(shí)點(diǎn)就是證書(shū)(后面仔細(xì)講),其實(shí)當(dāng)你身份驗(yàn)證完成后其實(shí)你就沒(méi)法對(duì)發(fā)送的消息進(jìn)行否認(rèn)了,因?yàn)閯e人無(wú)法偽造;
那既然我們知道了 HTTP 的信息傳輸過(guò)程中存在的這些問(wèn)題,那我們接下來(lái)就進(jìn)入正題,看看 HTTPS 如何解決掉這些問(wèn)題。
HTTPS 介紹
了解通信流程之前,還需要先對(duì) HTTPS 簡(jiǎn)單做個(gè)介紹,為什么 HTTPS 可以保障安全,它和 HTTP 到底有什么區(qū)別和聯(lián)系?
其實(shí) HTTPS = HTTP over SSL / TLS,這樣看的話,其實(shí)它和 HTTP 的區(qū)別就是在于多了 SSL / TLS,所以 HTTPS 的密鑰協(xié)商、傳遞、加密解密也肯定都是由 SSL / TLS 完成的。至于 SSL 和 TLS 的區(qū)別其實(shí)是 TLS 是 SSL 的升級(jí)版,一開(kāi)始 HTTPS 剛出來(lái)的時(shí)候安全層是 SSL,后來(lái)協(xié)議標(biāo)準(zhǔn)化,就在 SSL 的基礎(chǔ)上進(jìn)行優(yōu)化修改并且將其改名為 TLS。
原本 HTTP 的數(shù)據(jù)是會(huì)扔給 TCP 進(jìn)行處理發(fā)送的,而 HTTPS 中成了 HTTP 數(shù)據(jù)扔給 SSL / TLS 加密處理,然后在由 SSL / TLS 扔給 TCP,對(duì)方收到后也是 TCP 扔給 SSL / TLS 進(jìn)行解密,最后扔給 HTTP?,F(xiàn)在像是在這兩者之間插入了一層,所以我一般也稱(chēng) SSL / TLS 為安全層。
HTTP -> TCP(HTTP)
HTTP -> TLS -> TCP(HTTPS)
介紹完了什么是 HTTPS 后,如果只用一句話概括它,其實(shí) HTTPS 的本質(zhì)就是用非對(duì)稱(chēng)加密協(xié)商出一套對(duì)稱(chēng)加密密鑰。然后數(shù)據(jù)的傳遞都是通過(guò)對(duì)稱(chēng)加密去做。這樣既保障了安全又保障了效率。
保障效率是因?yàn)楹罄m(xù)真正的數(shù)據(jù)傳輸其實(shí)是通過(guò)對(duì)稱(chēng)加密來(lái)完成的,相比之下,非對(duì)稱(chēng)加密由于涉及到到大量運(yùn)算,執(zhí)行起來(lái)比對(duì)稱(chēng)加密要慢,而保障安全是因?yàn)閷?duì)稱(chēng)加密密鑰的傳輸是通過(guò)非對(duì)稱(chēng)加密的方式解決掉的。
HTTPS 通信流程
下面就來(lái)看看 HTTPS 的通信流程吧。
先來(lái)看下面這張圖:
TLS 或 HTTP 下層都是 TCP,所以不管怎樣我們都需要先通過(guò) TCP 三次握手來(lái)建立連接,然后再在這個(gè)連接基礎(chǔ)上,進(jìn)行 TLS 的握手。粗略的看話,我覺(jué)得 TLS 握手主要包括以下內(nèi)容:
- 客戶端請(qǐng)求建立 TLS 連接;
- 服務(wù)器返回信息和發(fā)回證書(shū);
- 客戶端驗(yàn)證服務(wù)器證書(shū);
- 客戶端信任服務(wù)器后,開(kāi)始與服務(wù)器協(xié)商對(duì)稱(chēng)加密密鑰;
- 驗(yàn)證密鑰是否可用和使用對(duì)稱(chēng)密鑰開(kāi)始通信;
如果仔細(xì)來(lái)看的話,我建議看著下面這張圖:
那讓我們?cè)賮?lái)詳細(xì)的展開(kāi)以下這個(gè) TLS 的握手流程:
- Client Hello,也就是告訴對(duì)方我想和你建立 TLS 連接,主要是協(xié)商加密方案和發(fā)送隨機(jī)數(shù);
- 附加內(nèi)容列一下:
- TLS 版本;
- 可選的對(duì)稱(chēng)加密算法;
- 可選的非對(duì)稱(chēng)加密算法;
- 可選的 Hash 算法(信息完整性計(jì)算時(shí)使用);
- 客戶端隨機(jī)數(shù)(客戶端和服務(wù)端的隨機(jī)數(shù)都是用來(lái)后續(xù)對(duì)稱(chēng)密鑰生成的);
- 附加內(nèi)容列一下:
- Service Hello,服務(wù)端會(huì)返回確認(rèn)后的加密方案和隨機(jī)數(shù);
- 附加信息也都是確認(rèn)信息,如下:
- 確認(rèn)的 TLS 版本;
- 確認(rèn)的對(duì)稱(chēng)加密算法;
- 確認(rèn)的非對(duì)稱(chēng)加密算法;
- 確認(rèn)的 Hash 算法;
- 服務(wù)器隨機(jī)數(shù);
- 附加信息也都是確認(rèn)信息,如下:
- 接下來(lái)服務(wù)器還會(huì)把證書(shū)發(fā)送過(guò)來(lái),用于客戶端進(jìn)行驗(yàn)證服務(wù)端的身份;
- 意義在于服務(wù)器的公鑰在證書(shū)里,接下來(lái)用于讓客戶端拿驗(yàn)證好公鑰發(fā)消息給服務(wù)端;
- 具體驗(yàn)證細(xì)節(jié)和證書(shū)是什么會(huì)后面講;
- 如果是雙向驗(yàn)證客戶端也需要把自己證書(shū)發(fā)給服務(wù)端;
- 客戶端生成 pre-master 隨機(jī)數(shù),并用剛才驗(yàn)證過(guò)沒(méi)問(wèn)題的證書(shū)里的服務(wù)器公鑰進(jìn)行加密,傳輸給服務(wù)器;
- 兩邊通過(guò)這三個(gè)隨機(jī)數(shù)(客戶端隨機(jī)數(shù)、服務(wù)端隨機(jī)數(shù)以及剛生成的 pre-master)進(jìn)行對(duì)稱(chēng)加密的密鑰;
- 雖然客戶端隨機(jī)數(shù)、服務(wù)端隨機(jī)數(shù)是明文發(fā)送的,但是 pre-master 是使用服務(wù)端公鑰進(jìn)行傳輸?shù)?,所以就算別人拿到前兩個(gè)隨機(jī)數(shù),別人還是不知道實(shí)際的對(duì)稱(chēng)密鑰是什么,因?yàn)橹虚g人沒(méi)有拿到 pre-master,就沒(méi)法推算出真正的對(duì)稱(chēng)加密密鑰;
- 如果只是單向證書(shū)驗(yàn)證,其實(shí)只需要客戶端拿到服務(wù)器證書(shū)里面的公鑰進(jìn)行加密,然后后將加密后消息傳遞給服務(wù)端即可,但雙向驗(yàn)證時(shí),就需要客戶端不僅用服務(wù)端的公鑰加密,還需要用自己私鑰對(duì)加密后的內(nèi)容簽名,從而確保安全和身份驗(yàn)證功能,這樣服務(wù)端拿到內(nèi)容先驗(yàn)簽再解密了;
- 這里的計(jì)算會(huì)生成四個(gè)東西:
- 客戶端加密密鑰,客戶端發(fā)過(guò)去的東西用這個(gè)加密,然后服務(wù)端收到后用它解密;
- 服務(wù)端加密密鑰,服務(wù)端發(fā)過(guò)去的東西用這個(gè)加密,然后客戶端收到后用它解密;
- 上面兩個(gè)為啥這么設(shè)計(jì)?為了區(qū)分是誰(shuí)發(fā)的,也防止消息被扔回去;
- 如果都使用同一把鑰匙那中間人雖然看不懂,但是可以扔回去,你也不知道這消息究竟是來(lái)自自己這邊的還是服務(wù)端那邊的;
- 客戶端 Mac secret;
- 服務(wù)端 Mac secret;
- Mac secret,是 HMAC(基于 Hash 消息認(rèn)證碼) secret,用來(lái)驗(yàn)證消息是否被篡改過(guò),和簽名的作用非常像,可以驗(yàn)證消息的完整性和來(lái)源(驗(yàn)證來(lái)源是因?yàn)閮蛇叺?HMAC 不一樣);
- 客戶端通知:將使用加密通信;
- Finished(并不是真的發(fā) Finished 這個(gè)幾個(gè)字母,是個(gè)信息指代);
- 這兩步也是為了驗(yàn)證一下,我們剛才商量好的對(duì)稱(chēng)密鑰行不行,我發(fā)給你你能不能解開(kāi);
- 把之前所有發(fā)送消息做一個(gè)摘要,然后加密,發(fā)過(guò)去讓服務(wù)器驗(yàn)證;
- 服務(wù)端通知:將使用加密通信;
- Finished;
- 這兩步只是上面的反過(guò)來(lái),這個(gè)也驗(yàn)證完就說(shuō)明兩邊發(fā)的對(duì)方都能看懂了,可以開(kāi)始正式通信了;
這就是我理解的 HTTPS 的通信流程了,不過(guò)剛才上面還缺失了重要一環(huán)也是證書(shū)驗(yàn)證的內(nèi)容,下面來(lái)主要講講證書(shū)驗(yàn)證。
證書(shū)驗(yàn)證
回想一下我們最開(kāi)始提到的如果愛(ài)麗絲想要和鮑勃使用非對(duì)稱(chēng)加密進(jìn)行安全通信的話,那就必須先讓愛(ài)麗絲拿到鮑勃的公鑰才行,有什么辦法可以拿到對(duì)方的公鑰嗎?
- 鮑勃把公鑰放在網(wǎng)站上別人去拿;
- 愛(ài)麗絲和鮑勃進(jìn)行通信時(shí),鮑勃發(fā)給愛(ài)麗絲;
如果仔細(xì)想想的話這兩種方式其實(shí)都有問(wèn)題,前者如果中間人伊芙引導(dǎo)你訪問(wèn)了錯(cuò)誤的網(wǎng)站就會(huì)導(dǎo)致你拿到錯(cuò)誤的公鑰,而后者伊芙可能在你們公鑰傳輸?shù)倪^(guò)程中對(duì)信息進(jìn)行攔截和篡改,所以愛(ài)麗絲想要拿到正確的鮑勃的公鑰并不容易。
那這個(gè)問(wèn)題有解決方案嗎?就是通過(guò)非對(duì)稱(chēng)加密的簽名來(lái)處理,但是鑒于沒(méi)法拿到正確的鮑勃的公鑰所以沒(méi)法讓鮑勃進(jìn)行簽名發(fā)送過(guò)來(lái),這時(shí)就需要一個(gè)第三方權(quán)威機(jī)構(gòu),我們都信任它,而它會(huì)用自己的私鑰對(duì)鮑勃的公鑰進(jìn)行簽名,然后我們只需要拿到這個(gè)第三方權(quán)威機(jī)構(gòu)的公鑰進(jìn)行驗(yàn)簽即可。
回到實(shí)際場(chǎng)景中來(lái),這個(gè)第三方機(jī)構(gòu),就是證書(shū)頒發(fā)機(jī)構(gòu),也被稱(chēng)為 CA(后面也都簡(jiǎn)寫(xiě)為 CA),如果服務(wù)端想讓 CA 給它頒發(fā)證書(shū)(信用背書(shū)),就會(huì)把自己的公鑰和身份信息發(fā)給 CA,CA 驗(yàn)證沒(méi)問(wèn)題后,生成證書(shū)信息,并且 CA 會(huì)對(duì)證書(shū)信息做一個(gè)摘要算法,就像提取指紋信息一樣,然后會(huì)對(duì)計(jì)算出來(lái)的 Hash 值進(jìn)行簽名,最后打包下發(fā)。
先來(lái)粗略看下證書(shū)里面都會(huì)包含什么信息:
- 要背書(shū)的公鑰;
- 證書(shū)所有者;
- 證書(shū)有效期;
- 證書(shū)發(fā)布機(jī)構(gòu);
- 簽名算法;
- ...;
那我們?cè)撊绾悟?yàn)證簽名呢?
- 先對(duì)服務(wù)端發(fā)來(lái)的證書(shū)用指定的摘要算法進(jìn)行摘要,得到指紋 P1;
- 然后使用這個(gè)證書(shū)頒發(fā) CA 的公鑰對(duì)他的數(shù)字簽名進(jìn)行驗(yàn)簽,得到指紋 P2;
- 最后看看 P1 和 P2 是否相等,相等就說(shuō)明證書(shū)沒(méi)有被竄改過(guò),如果不相同就說(shuō)證書(shū)被人篡改過(guò),因?yàn)?P2 是無(wú)法偽造的,CA 的簽名時(shí)使用的私鑰是只有 CA 自己才有;
但你可能會(huì)問(wèn),這個(gè)過(guò)程好像只是驗(yàn)證了給證書(shū)簽名時(shí)的 CA 私鑰和我們拿到的 CA 公鑰是對(duì)的上的,那如果 CA 證書(shū)下發(fā)過(guò)程本身就問(wèn)題怎么辦呢? 我怎么能確認(rèn)給這個(gè)服務(wù)端背書(shū)的 CA 是否可信呢?
要回答這個(gè)問(wèn)題其實(shí)并不難,就是讓那個(gè) CA 在找別的更大的更可信的 CA 給他做信用背書(shū),直到找到背后那幾個(gè)全球最大的 CA 機(jī)構(gòu),這些 CA 機(jī)構(gòu)也被稱(chēng)為 root CA,這些 CA 就已經(jīng)是我們無(wú)條件要相信的了,這就像你可以不相信同事告訴你的公司消息,但是同事告訴你這個(gè)消息是組長(zhǎng)告訴我的,你去問(wèn)了組長(zhǎng)還是不相信,組長(zhǎng)說(shuō)這個(gè)是經(jīng)理告訴我的,你去問(wèn)了經(jīng)理還是不相信,經(jīng)理說(shuō)這個(gè)是老板剛發(fā)的公司消息,最終你去問(wèn)了老板并確認(rèn)了消息,這時(shí)這條信任鏈就已經(jīng)完整構(gòu)建起來(lái)了。
所以給服務(wù)端下發(fā)證書(shū)的 CA(簡(jiǎn)稱(chēng) CA L),它的公鑰其實(shí)是另一個(gè)更大 CA(簡(jiǎn)稱(chēng) CA H)用自己的私鑰給它簽名的,也就是 CA H 會(huì)根據(jù) CA L 提供行公鑰和身份信息給它頒發(fā)證書(shū),然后這樣遞歸下去,直到我們剛剛說(shuō)的 root CA。
所以驗(yàn)證的順序也像圖中這樣,可能看圖更好理解,我要驗(yàn)證服務(wù)端證書(shū)就去找給中介 CA 拿它的公鑰進(jìn)行驗(yàn)簽(因?yàn)榉?wù)端證書(shū)是中介 CA 下發(fā)的),而中介 CA 證書(shū)驗(yàn)證又要去找 root CA 拿它的公鑰進(jìn)行驗(yàn)證(同理中介 CA 的證書(shū)是 root CA 下發(fā)的),那么 root CA 的公鑰在哪里呢?一般在操作系統(tǒng)里面都會(huì)有各大 root CA 的信息,當(dāng)然瀏覽器或者某些軟件(比如支付寶)里也會(huì)有。這時(shí)我拿到了 root CA 的公鑰信息,然后對(duì)中介 CA 證書(shū)進(jìn)行驗(yàn)證(證書(shū)驗(yàn)證過(guò)程上面已經(jīng)講到了),驗(yàn)證完成后拿到中介 CA 的公鑰再對(duì)服務(wù)端證書(shū)進(jìn)行驗(yàn)證,這樣如果都沒(méi)問(wèn)題,就說(shuō)明整條信任鏈?zhǔn)峭ǖ模乙部梢苑判哪梅?wù)端證書(shū)里的公鑰和對(duì)方進(jìn)行非對(duì)稱(chēng)加密通信了。
補(bǔ)充
- 服務(wù)端返回的是一個(gè)證書(shū)鏈,然后和你本地的根證書(shū)形成一個(gè)完整的驗(yàn)證鏈;
- root CA 的公鑰是在操作系統(tǒng)里或者軟件里,根證書(shū)沒(méi)有上層機(jī)構(gòu)再為其本身作數(shù)字簽名,所以都是自簽證書(shū);
- 自簽名證書(shū)就給人一種感覺(jué),我就是我,你愛(ài)信不信;
- 證書(shū)驗(yàn)證可以是單向的也可以雙向的,要看業(yè)務(wù)需求;
- 為什么 TLS 會(huì)有三個(gè)隨機(jī)數(shù)?
- TLS 設(shè)計(jì)者考慮的很周到,不相信“偽隨機(jī)“,為了保障更加隨機(jī),就把三個(gè)隨機(jī)數(shù)很合起來(lái)了;
- 只有你擁有對(duì)應(yīng)域名,你才能對(duì)其申請(qǐng)證書(shū);
- 再附上一張更詳細(xì)圖:
總結(jié)
到這里 HTTPS 的通信流程也就說(shuō)完了。
如果只用一句話總結(jié) HTTPS 就是它的本質(zhì)是通過(guò)非對(duì)稱(chēng)加密協(xié)商出一套對(duì)稱(chēng)密鑰,而后續(xù)真正數(shù)據(jù)都是使用對(duì)稱(chēng)加密進(jìn)行通信。
這里面的最難搞懂的點(diǎn)可能就是為什么要有證書(shū)和證書(shū)驗(yàn)證過(guò)程。
說(shuō)多了都是淚,希望看到這里之后 HTTPS 對(duì)你來(lái)說(shuō)就不是什么難理解的事情了。
感謝
以上內(nèi)容參考了扔物線的 HenCoder Plus、極客時(shí)間的《趣談網(wǎng)絡(luò)協(xié)議》、《透視 HTTP 協(xié)議》、《全棧工程師修煉指南》及 HTTPS 相關(guān)維基百科。
尤其是那兩張很全的 HTTPS 流程圖都是出自極客時(shí)間專(zhuān)欄,黑白的那種出自《趣談網(wǎng)絡(luò)協(xié)議》,而最后那張彩色的出自《透視 HTTP 協(xié)議》。
最后的最后
如果你覺(jué)得我寫(xiě)不錯(cuò),那就通過(guò)點(diǎn)贊,點(diǎn)贊,還 tm 是點(diǎn)贊的方式給我反饋吧,感謝你的支持。