大家好,我是滿天星,歡迎來到我的技術(shù)角落,本期我將帶你一起來了解 HTTPS。
PS:本文首發(fā)于微信公眾號(hào):技術(shù)角落。感興趣的同學(xué)可以查看并關(guān)注:https://mp.weixin.qq.com/s/HbEhD93S7y3p8amlzS2sKw
前言
其實(shí)網(wǎng)上寫 HTTPS 的文章也不少了,但是不少文章都是從原理上泛泛而談,只講概念,沒有講原因,作為小白,看完還是會(huì)有一種似懂非懂的感覺。
本文嘗試從 HTTP 開始,一步一步深入到 HTTPS,告訴你 HTTPS 到底是什么、為什么需要 HTTPS、以及 HTTPS 到底是怎么做的。相信你在閱讀完本文后,一定會(huì)對(duì) HTTPS 有深入的了解。
紙上得來終覺淺,除開原理部分外,本文還提供了 HTTP 和 HTTPS 的實(shí)戰(zhàn)教程,幫助你從 0 開始搭建一個(gè) HTTPS 加密的 Web 服務(wù)器,如果按照實(shí)戰(zhàn)教程一步一步走下來,那么你將對(duì) HTTPS 有更進(jìn)一步的把握。
好了,廢話不多說,直接進(jìn)入正題吧。
什么是 HTTPS ?一句話,HTTPS = HTTP + SSL。 HTTPS 并不是一個(gè)全新的協(xié)議,而是在 HTTP 的基礎(chǔ)上,通過 SSL 增加了一層加密協(xié)議,從而大大增加了 HTTP 協(xié)議的安全性。
所以在正式了解 HTTPS 之前,我們需要先了解 HTTP。
1. HTTP
HTTP 全稱 超文本傳輸協(xié)議(HyperText Transfer Protocol),是一種廣泛用于互聯(lián)網(wǎng)中瀏覽器與服務(wù)器之間的應(yīng)用層傳輸協(xié)議。簡單來說,瀏覽器向服務(wù)器發(fā)送 HTTP 請(qǐng)求,服務(wù)器向?yàn)g覽器返回 HTTP 響應(yīng),兩者之間通過這種方式進(jìn)行“交流”,來使得我們的瀏覽器可以正常從服務(wù)器端獲取數(shù)據(jù),并展示在用戶的電腦屏幕上。
以訪問 http://httpbin.org
網(wǎng)址為例,一個(gè)典型的 HTTP 請(qǐng)求如下所示:
GET / HTTP/1.1
Accept: text/html,...
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Host: httpbin.org
Pragma: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36
- GET 表示請(qǐng)求方法,常見的 HTTP 請(qǐng)求方法有 GET、POST、PUT、DELETE 等...
- GET 后面的
/
表示請(qǐng)求路徑,這里我們?cè)L問的根路徑,所以顯示為/
。如果你訪問httpbin.org/get
的話,這里顯示的就是/get
了 - HTTP/1.1 表示使用的 HTTP 協(xié)議版本,現(xiàn)在常用的有 HTTP/1.1 和 HTTP/2,當(dāng)然還有更先進(jìn)的 HTTP/3,這里就不過多展開了
- 下面的 9 行全部都是 HTTP header,每一個(gè) header 包含 name 和 value,之間用冒號(hào)分隔開。
一個(gè)典型的 HTTP 響應(yīng)如下所示
HTTP/1.1 200 OK
Date: Sat, 08 Apr 2023 16:28:43 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
body...
- HTTP/1.1 指的協(xié)議版本,響應(yīng)和請(qǐng)求的協(xié)議版本是一致的
- 200 OK 代表返回的響應(yīng)碼,表示這個(gè)響應(yīng)是符合預(yù)期的。另外還有非常常見的返回碼 404 NOT FOUND ,大家應(yīng)該或多或少聽說過,它表示服務(wù)器告訴你你訪問的這個(gè)資源不存在
- 后面 7 行全部是 HTTP header,同樣每一個(gè) header 包含 name 和 value,之間用冒號(hào)分隔開。
- 最后是 HTTP Body,也就是響應(yīng)體,即服務(wù)器返回給你的內(nèi)容主體,瀏覽器正是根據(jù)響應(yīng)體來渲染頁面的
由于本文重點(diǎn)不在 HTTP,這里不再詳細(xì)介紹各個(gè)部分的作用。
如果你對(duì) HTTP 還不太了解的話,我在本文附錄部分準(zhǔn)備了一份 HTTP 實(shí)戰(zhàn),建議你跟著實(shí)操一遍,了解下 HTTP 的基本結(jié)構(gòu)。當(dāng)然,這部分內(nèi)容比較基礎(chǔ),如果你已經(jīng)對(duì) HTTP 比較熟悉的話,這部分可以跳過了。
2. 為什么需要 HTTPS
上面簡單講了一下 HTTP。在正式講 HTTPS 之前,首先我們要搞清楚 HTTP 的缺點(diǎn)是什么,為什么需要 HTTPS。
我們知道,HTTP (除了最新的 HTTP/3 外),傳輸層是基于 TCP 協(xié)議的。TCP 建立連接時(shí),有三次握手。三次握手完畢之后,TCP 連接就順利建立了,接下來兩端將會(huì)傳輸數(shù)據(jù)。
對(duì)于普通的 HTTP 協(xié)議,在建立完 TCP 連接之后,就直接開始傳輸數(shù)據(jù)了,這時(shí)候數(shù)據(jù)是明文傳輸?shù)?,這也是 HTTP 最不安全的地方。
明文傳輸是什么概念呢?我們知道,瀏覽器和服務(wù)器之間,是存在很長一條路線的,你在家里通過瀏覽器訪問網(wǎng)頁的時(shí)候,數(shù)據(jù)會(huì)從你的電腦,傳到你家里的路由器,再到光貓,到運(yùn)營商,到互聯(lián)網(wǎng)....直到最后才到服務(wù)器。在明文傳輸下,理論上來講,瀏覽器和服務(wù)器之間的任一節(jié)點(diǎn),包括你家里的路由器、包括你購買寬帶/流量的運(yùn)營商,都可以“竊聽”你們的數(shù)據(jù),甚至還可以修改數(shù)據(jù)。
聽起來不夠直觀?打個(gè)比方,近代時(shí)期,戰(zhàn)場(chǎng)上打仗時(shí),部隊(duì)之間會(huì)通過電臺(tái)進(jìn)行交流。如果通過明文進(jìn)行交流,那么非常危險(xiǎn),敵軍可以打開電臺(tái)進(jìn)行竊聽,偷取你的軍事情報(bào),這樣的事也屢見不鮮了...那么他們是如何解決這個(gè)問題的呢?兩個(gè)部隊(duì)之間提前約定一個(gè)加密的方案,在傳數(shù)據(jù)之前,先把它進(jìn)行加密再傳輸,另一端收到數(shù)據(jù)之后,按照事先約定的方案進(jìn)行解密,然后讀取就可以了。這樣即使敵軍開始竊聽,也只能聽到加密后的情報(bào),如果無法對(duì)其破解的話,得不到任何有效信息。
沒錯(cuò),這就是 HTTPS 的思想,瀏覽器在發(fā)送 HTTP 請(qǐng)求之前,先通過某種方式對(duì)其進(jìn)行加密,然后再進(jìn)行傳輸。服務(wù)器端收到數(shù)據(jù)之后,對(duì)其解密,讀取真實(shí)內(nèi)容,生成 HTTP 響應(yīng),同樣對(duì)響應(yīng)進(jìn)行加密,然后傳回給瀏覽器,瀏覽器收到數(shù)據(jù)之后,對(duì)其進(jìn)行解密,得到真正的 HTTP 響應(yīng)。這樣就可以保證數(shù)據(jù)在傳輸過程中的安全性,無論是路由器還是運(yùn)營商,都沒有辦法“竊聽”你們的數(shù)據(jù)了。
說到這里,想必你已經(jīng)知道 HTTPS 的一大作用了,它可以保證數(shù)據(jù)在互聯(lián)網(wǎng)上傳輸?shù)陌踩裕苊庵虚g節(jié)點(diǎn)進(jìn)行竊聽和修改。
當(dāng)然,聰明的你還可能會(huì)想到一些問題,例如:
- 戰(zhàn)場(chǎng)上軍隊(duì)之間是提前約定好加密方案的,但是咱們?nèi)我庖粋€(gè)瀏覽器都可以隨時(shí)訪問網(wǎng)頁,沒有辦法提前約定加密方案呀,那是怎么做到的呢?
- 戰(zhàn)場(chǎng)上經(jīng)常出現(xiàn)敵軍對(duì)另一方部隊(duì)之間的電臺(tái)加密進(jìn)行破解的事情,破解完成之后,還是能夠竊聽到數(shù)據(jù),那 HTTPS 的這個(gè)加密方案到底安全嗎,會(huì)被破解嗎?
別急,這些問題,你都可以在本文中得到答案。
3. HTTP + SSL = HTTPS !
上面提到了對(duì) HTTP 進(jìn)行加密的思想。在 HTTPS 的具體實(shí)現(xiàn)中,這個(gè)加密方案即是大名鼎鼎的 SSL(Secure Sockets Layer)。
定義:SSL(Secure Sockets Layer)是一種安全協(xié)議,用于在互聯(lián)網(wǎng)上保護(hù)數(shù)據(jù)的傳輸安全。它工作在傳輸層,主要功能是通過加密技術(shù),保護(hù)不同計(jì)算機(jī)之間的數(shù)據(jù)傳輸過程,防止敏感數(shù)據(jù)被黑客竊取和篡改。SSL 協(xié)議可以用于保護(hù)網(wǎng)站的用戶登錄、信用卡支付、網(wǎng)上銀行等敏感信息的傳輸,以及企業(yè)之間的機(jī)密數(shù)據(jù)的傳輸。SSL 協(xié)議目前已經(jīng)被繼承為 TLS(Transport Layer Security),是一種安全性更高的傳輸層協(xié)議。所以,下面我將統(tǒng)一以 TLS 為名稱進(jìn)行講解。
首先,劃重點(diǎn),TLS 中有 Transport Layer,顧名思義,它一定是工作在傳輸層了。上面提到過,HTTP 是應(yīng)用層協(xié)議,傳輸層和應(yīng)用層的概念,想必大家應(yīng)該知道吧,計(jì)算機(jī)網(wǎng)絡(luò)的事實(shí)標(biāo)準(zhǔn)中,自頂向下可以分為五層:應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、鏈路層、物理層...這是《計(jì)算機(jī)網(wǎng)絡(luò)》的基礎(chǔ),這里不過多展開,不熟悉的同學(xué),要回去重修一下課程了。
我們知道,TCP 協(xié)議里有三次握手,三次握手成功后連接才算建立,接下來才會(huì)真正開始傳輸數(shù)據(jù)。傳統(tǒng)的 HTTP 協(xié)議中,三次握手成功之后,就會(huì)直接開始明文傳輸 HTTP 數(shù)據(jù)了。
那么 TLS 是什么時(shí)候開始發(fā)揮作用的呢?答案很簡單,在三次握手之后,傳輸數(shù)據(jù)之前。
也就是說,在 TCP 協(xié)議中加入 TLS 之后,三次握手成功之后就不會(huì)再立刻開始傳輸數(shù)據(jù)了,而是緊接著開始 TLS 的建立過程,也被稱為 TLS 握手。
TLS 握手是干嘛呢?或者說為什么需要 TLS 握手呢?上面提到,在戰(zhàn)場(chǎng)上,兩個(gè)部隊(duì)之間會(huì)提前約定好加密的方案,例如面對(duì)面用紙互相寫下加密方案,然后在一段時(shí)間之內(nèi)的電臺(tái)通信統(tǒng)一用這個(gè)加密方案,這樣能一定程度上保證電臺(tái)通信的安全性。但是 TLS 中我們并沒有這樣一個(gè)“面對(duì)面”的機(jī)會(huì),咱們總不可能在訪問網(wǎng)頁之前,人肉跑到服務(wù)器的維護(hù)者那邊去跟他約定加密方案吧。出于這個(gè)目的,TLS 握手便出現(xiàn)了。所以我們可以說,TLS 握手的目的是給通信雙方約定一個(gè)安全的加密方案(可以理解為商量一個(gè)只有雙方知道的加密密鑰)。
知道了 TLS 握手的目的,接下來我們需要知道它具體是怎么做的。首先,我們肯定不能直接明文傳輸加密方案(密鑰),不然這個(gè)密鑰在傳輸過程中就直接被第三方獲取了,那么加密將沒有任何意義。也就是說,TLS 握手需要做到:通信雙方可以約定一個(gè)共同的加密方案(密鑰),并且這個(gè)約定的過程(即 TLS 握手過程),即使被任何第三方竊聽到,也無法解析出這個(gè)加密方案(密鑰) 。
是不是聽起來很神奇,那到底是怎么做到的呢?這就不得不提到密碼學(xué)中非常經(jīng)典的兩個(gè)概念:對(duì)稱加密和非對(duì)稱加密。
4. 對(duì)稱加密,非對(duì)稱加密
·
對(duì)稱加密是 TLS 握手成功后,通信雙方之間采用的數(shù)據(jù)加密方案?,F(xiàn)在的主要問題是:通信雙方如何安全的商量好這個(gè)對(duì)稱密鑰,防止密鑰被其他人竊???
這時(shí)就需要輪到非對(duì)稱加密出場(chǎng)了。什么是非對(duì)稱加密呢?與對(duì)稱加密不同,非對(duì)稱加密方案中,用戶手握兩把密鑰,一把稱為公鑰,一把稱為私鑰,其中公/私鑰都可以用來加密/解密數(shù)據(jù),但是:用公鑰加密后的數(shù)據(jù),只有用私鑰才能將其解開;用私鑰加密后的數(shù)據(jù),只有用公鑰才能將其解開!
這里只介紹了非對(duì)稱加密的特點(diǎn),并沒有介紹其原理,因?yàn)檫@屬于密碼學(xué)的范疇了,展開來講又是一篇文章。簡單說說其思想吧,目前流行的非對(duì)稱加密算法 RSA 基于的原理其實(shí)就一句話:我們目前還沒有很好的辦法對(duì)一個(gè)很大的數(shù)做因式分解,例如你在心里默默想一個(gè)很大的質(zhì)數(shù) p 和 質(zhì)數(shù) q,算出其乘積 n,那么向外公開 n 的話,外部人員是很難找出 p 和 q 的(只能暴力嘗試,而當(dāng)這樣的數(shù)夠大夠多的時(shí)候,以現(xiàn)在的計(jì)算機(jī)算力也需要幾百上千年的時(shí)間才能破解了)。對(duì)密碼學(xué)感興趣的同學(xué),可自行進(jìn)一步了解。
有了非對(duì)稱加密,事情就變得有意思起來了。見下圖,服務(wù)器端用非對(duì)稱加密方案生成一對(duì)公/私鑰,私鑰掌握在自己手里,誰也不告訴;在 TLS 握手的過程中,服務(wù)器將自己的公鑰交給瀏覽器端,瀏覽器端在心里默默想出一個(gè)對(duì)稱加密的密鑰后,將這個(gè)密鑰用服務(wù)器端的公鑰進(jìn)行加密,然后再傳回給瀏覽器端;瀏覽器端收到這個(gè)數(shù)據(jù)之后,用自己的私鑰將其進(jìn)行解密,就能夠得到剛才瀏覽器心里默念的那個(gè)對(duì)稱密鑰了。這樣這個(gè)問題就完美的解決了,兩邊可以心有靈犀的拿到這個(gè)對(duì)稱密鑰,而不用擔(dān)心被任何第三方竊取到了。
這就是 TLS 握手的過程嗎?不,當(dāng)然沒這么簡單了,我們還沒有考慮一個(gè)非常巧妙的攻擊手段:中間人攻擊。
5. 中間人攻擊
具體什么是中間人攻擊呢?看下面這張圖
假設(shè)現(xiàn)在我們從電腦上訪問百度,如果有一個(gè)中間人在我的路由器端,或者運(yùn)營商端,或者任何一個(gè)中間節(jié)點(diǎn)上截取了我的請(qǐng)求,剛不是提到服務(wù)器端需要返回給我們公鑰嗎,中間人他自己也生成一套公/私鑰,然后將自己的公鑰返回給我,這樣我就與中間人之間建立了一條我以為“安全”的連接了,此時(shí)我以為我連接的是百度服務(wù)器,其實(shí)我連接的是中間人...那么此時(shí)中間人可以做任何事情了,如果他人品比較好的話,他可以默默當(dāng)一個(gè)代理,我要訪問百度,他就去幫我訪問百度,然后把結(jié)果返回給我,勤勤懇懇做一個(gè)“中間商”。當(dāng)然,我們知道做這種攻擊的人人品往往不會(huì)太好,所以他們可以做更壞的事情,例如偽造一個(gè)銀行網(wǎng)頁返回給我,讓我填寫賬號(hào)和密碼,這樣的話...后果就不堪設(shè)想了。
那么如何防止中間人攻擊呢?其中的核心就是:我們需要保證我們?cè)L問的就是目標(biāo)服務(wù)器,例如,當(dāng)我們?cè)L問百度時(shí),我們需要確保在 TLS 握手時(shí),給我們公鑰的人就是百度,而不是任何其他人。
那么這個(gè)應(yīng)該如何去保證呢?這就不得不提到接下來的幾個(gè)概念了,數(shù)字證書,以及證書權(quán)威機(jī)構(gòu)(Certificate Authority,簡稱 CA)。
6. 數(shù)字證書、CA
數(shù)字證書是由證書權(quán)威機(jī)構(gòu)(CA)頒發(fā)的一個(gè)用于證明身份的證書,當(dāng)然其中還包含了該用戶的公鑰等信息。例如還是以百度為例,假設(shè)百度需要給 www.baidu.com
這個(gè)域名申請(qǐng)一個(gè)數(shù)字證書,他需要在生成公鑰/私鑰后,將自身的信息(包括域名、公司名稱、公鑰信息等)發(fā)給某個(gè)證書權(quán)威機(jī)構(gòu)(CA),讓 CA 給自己頒發(fā)一個(gè)數(shù)字證書。CA 需要驗(yàn)證百度的真實(shí)身份,并且他確實(shí)擁有 www.baidu.com
這個(gè)域名,一切都驗(yàn)證通過后,CA 才會(huì)給百度頒發(fā)這么一個(gè)數(shù)字證書。那么之后,不管是誰用瀏覽器訪問 www.baidu.com
的時(shí)候,百度都會(huì)將剛才那個(gè) CA 頒發(fā)的數(shù)字證書發(fā)送給用戶,既可以用來自證身份,同時(shí)還順便告訴了用戶自己的公鑰。
到這里你可能還會(huì)有幾個(gè)疑問:
- 數(shù)字證書如何保證不能偽造呢,難道中間人不能偽造一個(gè)數(shù)字證書發(fā)送給用戶嗎?
- 即使數(shù)字證書不能被偽造,從概念上看他是公開的,難道中間人不能直接把這個(gè)證書頒發(fā)給用戶嗎?
下面會(huì)一一回答這幾個(gè)問題。正式回答之前,先來看看數(shù)字證書里究竟有哪些內(nèi)容。
既然上面提到百度,我們就以百度為例,我們使用瀏覽器訪問百度,可以在地址欄左邊看到一個(gè)小鎖,點(diǎn)擊后,就可以查看百度的數(shù)字證書
圖中可以看到該證書的一些基本信息:
- 頒發(fā)對(duì)象:這個(gè)證書是頒發(fā)給百度的,并且只對(duì)域名 (www.)baidu.com 有效
- 頒發(fā)者:這個(gè)證書是由 GlobalSign 頒發(fā)的。(GlobalSign是一家全球知名的證書權(quán)威機(jī)構(gòu))
- 有效期:這個(gè)證書的有效期是從 2022 年 7 月到 2023 年 8 月。(一旦過期,證書將不被信任)
- 指紋:指紋是整張證書經(jīng)過哈希計(jì)算后得到的特征值,主要與后面會(huì)提到的簽名一起工作,起到防篡改的作用
當(dāng)然,一張數(shù)字證書的內(nèi)容遠(yuǎn)遠(yuǎn)不止于此,例如還包含了服務(wù)器的公鑰,可以在“詳細(xì)信息”中進(jìn)行查看。
下面我們?cè)谧C書詳細(xì)信息中點(diǎn)擊“導(dǎo)出”,將證書導(dǎo)出為 Base64 編碼的單一證書,然后使用 openssl 對(duì)其進(jìn)行解析和查看
$ openssl x509 -noout -text -in baidu.com.cer
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
44:17:ce:86:ef:82:ec:69:21:cc:6f:68
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=BE, O=GlobalSign nv-sa, CN=GlobalSign RSA OV SSL CA 2018
Validity
Not Before: Jul 5 05:16:02 2022 GMT
Not After : Aug 6 05:16:01 2023 GMT
Subject: C=CN, ST=beijing, L=beijing, OU=service operation department, O=Beijing Baidu Netcom Science Technology Co., Ltd, CN=baidu.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:aa:2f:cc:41:8d:25:ae:83:e9:f4:27:c4:00:b3:
39:6f:0e:98:2a:55:7d:07:e5:80:49:82:fa:d3:d3:
85:98:b5:df:7b:6f:bb:02:dd:ed:78:e4:0c:07:2b:
9e:1e:86:4b:f6:6a:86:58:d7:57:6f:21:59:11:d8:
6f:96:6e:d2:de:36:28:f6:b4:e3:ce:95:32:29:00:
c1:65:8e:69:b0:00:fe:52:37:f4:88:3f:8b:6d:0f:
bb:f0:ec:c5:c0:31:ef:ad:b5:0c:06:66:ad:be:dc:
43:13:c4:66:b0:5d:cf:56:53:e2:d1:96:82:1c:06:
bb:9b:5f:ed:60:8d:d2:ed:f3:d2:50:ee:bb:cd:b2:
36:97:c8:ce:7b:d2:4b:b7:5c:b4:88:ca:37:6e:8b:
ce:f9:96:fd:b4:f5:47:b5:20:77:bb:fc:a8:9d:81:
b2:6c:f8:c7:09:6a:dd:22:6e:83:3f:a7:53:df:f1:
da:2f:29:6b:22:c3:e9:1d:65:e8:c5:a0:ba:13:4e:
16:3f:03:93:f0:a5:59:8a:1a:80:e8:27:7d:49:23:
df:d1:f9:4b:97:b7:01:c4:19:f5:f1:c5:ff:91:33:
d0:a1:74:c6:ee:d4:cf:f6:38:0c:ed:bd:5e:aa:44:
fb:88:f7:7b:99:70:76:34:55:7e:55:d2:0f:9e:bf:
94:93
... (中間省略)
Signature Algorithm: sha256WithRSAEncryption
63:21:07:23:47:06:eb:b3:7c:77:6c:df:bc:55:12:b9:f1:5e:
6a:04:60:16:be:d0:0b:18:9c:94:0c:a8:82:08:25:0d:26:fb:
dd:cb:fc:8c:27:d9:0c:fa:4a:b6:31:b6:67:f0:26:2c:0d:96:
96:39:65:3f:d9:a1:ee:de:9c:10:4d:54:e1:c8:d6:a9:0e:77:
db:00:e2:37:e3:3f:b4:9c:31:4f:ac:74:d3:22:12:53:36:d0:
ef:18:07:2d:8e:d0:e6:91:b2:6c:4a:5e:39:53:14:58:4e:d1:
50:04:c9:83:7e:0d:7b:15:96:87:11:d7:5d:4a:17:ac:aa:9f:
84:e3:a8:24:9d:d6:17:77:26:8c:9f:7a:7b:18:da:39:2f:77:
f7:2b:c7:23:b8:97:6f:c3:d1:72:4c:7e:fc:c6:0d:cc:73:38:
19:81:fb:e7:c1:7a:e8:b9:1d:3a:05:dc:36:04:9b:f1:f0:e1:
a6:47:a0:30:4f:55:90:6c:da:cf:9e:b2:76:12:11:a1:5c:b6:
61:8d:15:a4:68:65:9a:57:2f:7a:6e:a3:1f:f5:b4:92:5a:3c:
df:71:0a:cd:57:d4:d0:15:36:7e:ba:d5:03:25:27:45:b4:60:
cd:2e:02:c1:0f:0a:e7:41:6f:58:69:20:9e:ad:47:52:1a:b5:
e6:e5:8d:1d
可以看到,除了上面 Chrome 里顯示的一些基本信息外,證書里還包含了幾個(gè)重要信息:
- 服務(wù)器端的公鑰,即上面 RSA Public-Key 下面的那一長串?dāng)?shù)字,就是百度的公鑰了。
- 簽名,證明數(shù)字證書有效的關(guān)鍵信息。如果把數(shù)字證書類比成一張合同的話,我們知道合同需要老板簽字才算有效,同樣,數(shù)字證書是需要 CA 簽名才算有效的,這里的一長串字符就是 CA 對(duì)該證書的“簽名”了。
我們知道合同上的簽名是靠筆跡鑒定來確認(rèn)真?zhèn)蔚?,很明顯這一長串字符里沒有筆跡,那它是如何保證該簽名是 CA 頒發(fā)的,而不是被其他人偽造的呢?
上面我們提到,每一張數(shù)字證書有一個(gè)指紋,是將整張證書經(jīng)過哈希運(yùn)算后得到的特征值。CA 作為權(quán)威機(jī)構(gòu),其本身也是有一對(duì)公鑰/私鑰的,它在頒發(fā)數(shù)字證書的時(shí)候,會(huì)用自己的私鑰對(duì)證書的指紋進(jìn)行加密,生成的這段加密數(shù)據(jù),就是該證書的簽名了!那么我們?yōu)g覽器是如何驗(yàn)證證書的真?zhèn)文??我們只需要使?CA 的公鑰對(duì)簽名進(jìn)行解密,看看得到的值是不是跟證書的指紋是一樣的,這樣就 OK 了,只要是一樣,說明這個(gè)證書一定是 CA 頒發(fā)的。
那么,又有問題來了:我們?yōu)g覽器是從哪里拿到 CA 的公鑰呢?總不能還是通過網(wǎng)絡(luò)傳輸吧,這樣就有“套娃”的中間人攻擊風(fēng)險(xiǎn)了。所以啊,我們的瀏覽器或操作系統(tǒng)已經(jīng)內(nèi)置了世界權(quán)威的 CA 的數(shù)字證書(證書里就包含了其公鑰)了,點(diǎn)擊瀏覽器的 設(shè)置 -> 隱私設(shè)置和安全性 -> 安全 -> 管理設(shè)備證書,可以查看當(dāng)前系統(tǒng)內(nèi)置的所有 CA 證書。
上圖是我的電腦中內(nèi)置的 CA 證書。剛剛提到了百度的數(shù)字證書是由 GlobalSign 頒發(fā)的,這里也可以驗(yàn)證,GlobalSign 是被我們的操作系統(tǒng)所信任的 CA,并且我們已經(jīng)將它的證書內(nèi)置在操作系統(tǒng)中了。因此現(xiàn)在我們可以認(rèn)定說,這個(gè)證書是值得信任的,與我們建立連接的就是百度,不是別人。
你可能會(huì)想,如果中間人將百度真實(shí)的數(shù)字證書返回給我呢?中間人是沒有百度的私鑰的,所以當(dāng)我們提取出證書中的公鑰,并對(duì)心里想的密鑰進(jìn)行加密后,中間人是解不開這個(gè)密鑰的,所以中間人無論如何也無法與我們建立連接。
好了,數(shù)字證書的內(nèi)容已經(jīng)全部講述完畢了,最后回過頭來復(fù)習(xí)下前面提到的兩個(gè)問題:
- 數(shù)字證書如何保證自身不會(huì)被偽造?
數(shù)字證書中有一段簽名,該簽名是 CA 使用其私鑰對(duì)證書指紋進(jìn)行加密后得到的值,我們?yōu)g覽器使用 CA 的公鑰對(duì)該簽名進(jìn)行解密后,與該證書的指紋進(jìn)行對(duì)比,就可以知道證書是否被篡改或者偽造了。
當(dāng)然,這里要多提一嘴,我們作為客戶端,需要保證自己的電腦里保存的都是值得信任的 CA 根證書,因?yàn)樾湃文?CA 就代表信任了該 CA 頒發(fā)的所有數(shù)字證書,如果有人/軟件想在你的電腦里安裝來歷不明的 CA 證書,那你就要保持警惕了...
- 如果中間人直接把真實(shí)的數(shù)字證書返回給我,它能夠成功與我建立連接嗎?
答案是不行的。這個(gè)問題其實(shí)比較簡單,剛剛提到,服務(wù)器端除了公鑰外,自身還保存有一份私鑰的,而中間人是拿不到這個(gè)私鑰的,因?yàn)樗环?wù)器雪藏起來,不會(huì)發(fā)送到互聯(lián)網(wǎng)中的...那么如果中間人用服務(wù)器的證書返回給用戶,用戶采用服務(wù)器的公鑰對(duì)自身默念出來的對(duì)稱密鑰進(jìn)行加密后,返回給中間人的時(shí)候,中間人就一臉懵逼了,因?yàn)檫@個(gè)密鑰它解不開呀,它沒有私鑰的,所以這個(gè)問題就完美解決了。
7. TLS 握手具體過程
最后,我們?cè)偻晖暾v一下 TLS 握手的具體流程。
上圖來自 www.ssl.com
,展示了整個(gè)握手流程,我用大白話解釋一下:
- 客戶端向服務(wù)器發(fā)送 Client Hello 信息,告知自己想要建立一條 TLS 連接,并告知自己支持的加密算法。
- 服務(wù)器向客戶端發(fā)送一個(gè) Server Hello 的回應(yīng),并選擇一個(gè)加密算法,同時(shí)給客戶端發(fā)送自己的數(shù)字證書(包含服務(wù)器的公鑰)。
- 客戶端驗(yàn)證服務(wù)器發(fā)來的數(shù)字證書,驗(yàn)證通過后,在心里默默想出一個(gè) pre-master 密鑰(預(yù)主密鑰),然后使用服務(wù)器的公鑰,將預(yù)主密鑰進(jìn)行加密后,發(fā)送給服務(wù)器。
- 服務(wù)器用自己的私鑰進(jìn)行解密,得到預(yù)主密鑰。
- 客戶端和服務(wù)器都通過預(yù)主密鑰,進(jìn)行相同的計(jì)算后,得到后續(xù)通信時(shí)使用的對(duì)稱加密密鑰,稱為 shared secret。
- 客戶端和服務(wù)器端都分別用生成的 shared-secret 加密一段報(bào)文后,發(fā)送給對(duì)方,以驗(yàn)證對(duì)方能夠成功收到信息并解密。
- 然后 TLS 就建立成功了,接下來雙方都用這個(gè) shared-secret 進(jìn)行加密通信。
總結(jié)一下,HTTPS 的加密過程中其實(shí)既用到了非對(duì)稱加密也用到了對(duì)稱加密,其中握手過程使用的是非對(duì)稱加密,主要目的是雙方可以安全的協(xié)商一個(gè)統(tǒng)一的密鑰,而真正的數(shù)據(jù)傳輸過程則使用的是對(duì)稱加密,正是使用剛才商量的這個(gè)密鑰。
你可能會(huì)問,為什么不全程使用非對(duì)稱加密呢?因?yàn)閷?duì)稱加密效率更高,尤其是在大量數(shù)據(jù)的時(shí)候,對(duì)稱加密比非對(duì)稱加密整整快幾個(gè)數(shù)量級(jí),所以真正數(shù)據(jù)傳輸?shù)倪^程選用了對(duì)稱加密。
到這里,HTTPS 的原理就已經(jīng)全部介紹完畢了。大家如果還有什么疑問,歡迎在評(píng)論區(qū)留言討論。
8. 總結(jié)
最后,我們總結(jié)一下,HTTPS 解決了兩個(gè)問題:
- 數(shù)據(jù)傳輸過程中的安全問題,因?yàn)樗鼘?duì)數(shù)據(jù)進(jìn)行了加密,只有瀏覽器和服務(wù)器可以對(duì)其進(jìn)行解密。
- 瀏覽器對(duì)服務(wù)器的信任問題,數(shù)字證書以及其中的數(shù)字簽名,保證了我們?cè)L問的就是我們想要訪問的服務(wù)器,不可能被釣魚網(wǎng)站欺騙,也不可能被中間人攻擊所欺騙。
當(dāng)然,保證以上安全的前提是我們的電腦本身沒有被攻破,如果你的電腦被黑客攻擊,裝上了來歷不明的根證書,那么 HTTPS 也不能保障你的安全了。
附錄一:HTTP 實(shí)戰(zhàn)
這里的實(shí)操部分針對(duì)不太熟悉 HTTP 的同學(xué),熟悉的同學(xué)請(qǐng)直接跳過...
在瀏覽器(建議 Chrome)中訪問httpbin.org
,并使用開發(fā)者工具進(jìn)行觀察
點(diǎn)擊 Request Headers 后面的 View source,可以看到原始的 HTTP 請(qǐng)求報(bào)文,摘抄如下
GET / HTTP/1.1
Accept: text/html,...
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Host: httpbin.org
Pragma: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36
其中:
- GET 表示請(qǐng)求方法,常見的 HTTP 請(qǐng)求方法有 GET、POST、PUT、DELETE 等...
- GET 后面的
/
表示請(qǐng)求路徑,這里我們?cè)L問的根路徑,所以顯示為/
。如果你訪問httpbin.org/get
的話,這里顯示的就是/get
了 - HTTP/1.1 表示使用的 HTTP 協(xié)議版本,現(xiàn)在常用的有 HTTP/1.1 和 HTTP/2,當(dāng)然還有更先進(jìn)的 HTTP/3,這里就不過多展開了
- 下面的 9 行全部都是 HTTP header,每一個(gè) header 包含 name 和 value,之間用冒號(hào)分隔開。
當(dāng)然,點(diǎn)擊 Response Headers 后面的 view source,你就可以看到服務(wù)器返回給你的 HTTP 響應(yīng)頭是怎么樣的了
HTTP/1.1 200 OK
Date: Sat, 08 Apr 2023 16:28:43 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
body...
- HTTP/1.1 指的協(xié)議版本,響應(yīng)和請(qǐng)求的版本肯定是一樣的了
- 200 OK 代表返回的響應(yīng)碼,表示這個(gè)響應(yīng)是 OK 的。另外還有非常常見的返回碼 404 NOT FOUND ,表示服務(wù)器告訴你你訪問的這個(gè)資源不存在...
- 后面 7 行全部是 HTTP header,同樣每一個(gè) header 包含 name 和 value,之間用冒號(hào)分隔開。
- 最后是 HTTP Body,也就是響應(yīng)體,在 Response Header 里是看不到了,不過點(diǎn)擊上面 Tab 頁的 Response 后,就可以看到完整的響應(yīng)體了。
由于本篇文章的重點(diǎn)不在 HTTP,這里就不再過多展開,非常建議大家平時(shí)使用瀏覽器訪問網(wǎng)頁的時(shí)候,有事沒事多打開下上面的開發(fā)者工具,看看 HTTP 到底是怎么工作的,說不定,還能找到一份工作呢...
(訪問百度時(shí),開發(fā)者工具中的小彩蛋)
當(dāng)然,作為程序員,還是希望有更“極客”的方式來了解 HTTP 協(xié)議,這時(shí)候就要用到 curl
命令了
終端里輸入 curl -v httpbin.org
,可以看到整個(gè) HTTP 交互的流程
附錄二:數(shù)字證書實(shí)戰(zhàn)
這部分實(shí)戰(zhàn)教程將帶你體驗(yàn) HTTPS 的全流程,從證書生成、到 HTTPS 服務(wù)器建設(shè)、到最后的瀏覽器訪問。教程將從以下三個(gè)方面進(jìn)行:
- 首先利用
openssl
工具,模擬一個(gè)證書權(quán)威機(jī)構(gòu)(CA),生成 CA 證書以及密鑰。 - 然后利用
openssl
工具,模擬techcorner.cn
網(wǎng)站的維護(hù)者,向上面的 CA 機(jī)構(gòu)申請(qǐng)一個(gè)數(shù)字證書 - 使用 Nginx 搭建自己的 HTTPS 服務(wù)器,并使用上面生成的服務(wù)器證書。
- 使用瀏覽器訪問自己搭建的 HTTPS 服務(wù)器,體會(huì)全加密流程。
值得一提的是,網(wǎng)上也有不少利用 openssl
生成證書的教程,但是它們質(zhì)量參差不齊,絕大多數(shù)都無法生成一個(gè)瀏覽器識(shí)別的、能夠真正用在生產(chǎn)環(huán)境中的證書。而本教程是我查閱官方文檔、并且親自試驗(yàn)過的教程,絕對(duì)有效。
實(shí)戰(zhàn)前,你需要準(zhǔn)備:
- Mac / Linux 服務(wù)器
- 安裝 openssl 工具、以及 Nginx 。
1. 生成 CA 證書
我們知道服務(wù)器拿到的數(shù)字證書都是從 CA 那邊頒發(fā)的,所以首先我們需要模擬出一個(gè) CA 機(jī)構(gòu),即生成 CA 證書以及密鑰。
首先生成 CA 私鑰(公鑰可以從私鑰中提取而來)
# 生成 CA 私鑰
openssl genrsa -out ca.key 2048
然后生成證書簽發(fā)申請(qǐng)文件
# 生成證書簽發(fā)申請(qǐng)文件(.csr)
openssl req -new -key ca.key -out ca.csr -subj '/C=CN/ST=Zhejiang/L=Hangzhou/O=Tech_Corner/CN=ROOTCA'
-subj
后面的參數(shù)代表了生成證書的基本信息,包括國家、省份、城市、公司名稱等。CN=ROOTCA,代表是準(zhǔn)備申請(qǐng)一個(gè)根證書。
然后根據(jù)上面生成的私鑰和證書申請(qǐng)文件,自簽一個(gè)根證書
# 自簽一個(gè)根證書
openssl x509 -req -days 365 -sha256 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.cer
總結(jié)一下,以上命令,一共生成了三個(gè)與 CA 有關(guān)的文件:
-
ca.key
:CA 私鑰 -
ca.csr
:CA 為自己簽發(fā)證書的請(qǐng)求。(該文件的作用是生成 CA 證書,生成之后不會(huì)再用到) -
ca.cer
:CA 為自己簽發(fā)的證書
可以用 openssl 命令,查看下申請(qǐng)的證書信息
$ openssl x509 -in ca.cer -text -noout
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
92:63:8f:e3:23:97:e1:c6
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=Zhejiang, L=Hangzhou, O=Tech_Corner, CN=ROOTCA
Validity
Not Before: Apr 11 15:39:56 2023 GMT
Not After : Apr 10 15:39:56 2024 GMT
Subject: C=CN, ST=Zhejiang, L=Hangzhou, O=Tech_Corner, CN=ROOTCA
... 以下省略
2. 生成服務(wù)器證書
接下來,我們模擬網(wǎng)站 techcorner.cn
的維護(hù)者,想要為自己的網(wǎng)站申請(qǐng)一個(gè)數(shù)字證書,所以我們需要向上面模擬的 CA 來申請(qǐng)證書。
同樣,我們首先生成一個(gè)自己的私鑰 。
openssl genrsa -out server.key 2048
然后,生成一個(gè)證書簽發(fā)申請(qǐng)文件
openssl req -new -key server.key -out server.csr -subj '/C=CN/ST=Zhejiang/L=Hangzhou/O=Tech_Corner/CN=techcorner.cn'
注意,這里 -subj
中有一個(gè)很重要的參數(shù)是 CN=techcorner.cn
,它代表我們生成的證書,只簽發(fā)給這個(gè)域名。換句話說,其他的域名如果使用這個(gè)證書,會(huì)被瀏覽器判斷為無效。
以上證書簽發(fā)申請(qǐng)文件(server.csr) 發(fā)送給 CA 后,CA 會(huì)對(duì)其做一些驗(yàn)證,例如驗(yàn)證申請(qǐng)者本身是不是符合資質(zhì),是不是確實(shí)擁有這個(gè)域名,等等。都確認(rèn)完畢后,CA 才會(huì)決定給用戶頒發(fā)這個(gè)證書。(CA 必須維護(hù)自己的權(quán)威性,隨便頒發(fā)證書的 CA 將被世界所拋棄,已經(jīng)有這樣的先例了)
CA 為其頒發(fā)證書的命令,可模擬如下
openssl x509 -req -extfile <(printf "subjectAltName=DNS:techcorner.cn,DNS:www.techcorner.cn") -days 365 -in server.csr -CA ca.cer -CAkey ca.key -CAcreateserial -out server.cer
其中比較有意思的是 -extfile
后面填寫的 subjectAltName=...
這一串,這其實(shí)是 X509 V3 證書里面的字段,對(duì)于普通的 TLS 加密,他可能不是必須的,但是對(duì)于 HTTPS,尤其是瀏覽器來說,它會(huì)額外對(duì)這個(gè)字段進(jìn)行校驗(yàn),確保其中存在當(dāng)前訪問的域名,否則即使 CN
滿足,瀏覽器同樣不會(huì)信任這個(gè)證書?。ňW(wǎng)上很多教程都沒有注意到這個(gè)地方,導(dǎo)致最后生成的證書不可用)
得到的服務(wù)器證書為 server.cer
。同樣可以使用 openssl 查看證書
$ openssl x509 -in server.cer -text -noout
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
80:56:02:4d:21:ff:5e:60
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=Zhejiang, L=Hangzhou, O=Tech_Corner, CN=ROOTCA
Validity
Not Before: Apr 11 15:52:10 2023 GMT
Not After : Apr 10 15:52:10 2024 GMT
Subject: C=CN, ST=Zhejiang, L=Hangzhou, O=Tech_Corner, CN=techcorner.cn
...以下省略
上面可以看到該證書的基本信息(Subject),以及頒發(fā)者信息(Issuer)等。
3. 啟動(dòng) Nginx,并使用上面生成的服務(wù)器證書
編輯 nginx.conf
,添加 HTTPS 端口的監(jiān)聽
server {
listen 443 ssl;
server_name techcorner.cn;
ssl_certificate /path/to/server.cer;
ssl_certificate_key /path/to/server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
-
ssl_certificate
的值修改為上一步生成的 server.cer 的絕對(duì)地址 -
ssl_certificate_key
的值修改為上一步生成的 server.key 的絕對(duì)地址
然后啟動(dòng) Nginx。
啟動(dòng)完畢后后,通過瀏覽器訪問 https://localhost:443
訪問 Nginx
可以看到瀏覽器給出了不安全的警告,這是符合預(yù)期的,因?yàn)槲覀兪褂玫淖C書是自己使用 openssl
簽發(fā)的,CA 機(jī)構(gòu)也是自己模擬的,并不在電腦的信任列表中。
如果想要正常訪問,可以在系統(tǒng)的根證書列表中,將我們自己模擬的 CA 證書添加進(jìn)去(Mac 系統(tǒng)中,將根證書 ca.cer
拖入鑰匙串訪問的 系統(tǒng) 中即可,并對(duì)其進(jìn)行 “始終信任”)。
這個(gè) CA 證書是我們自己生成的,只要我們自己不泄漏其私鑰,那么將是安全的
使用瀏覽器重新訪問 https://localhost:443
,得到如下結(jié)果
可以發(fā)現(xiàn)仍然是 不安全 的狀態(tài),不過這時(shí)錯(cuò)誤代碼已經(jīng)變了,剛才是 ERR_CERT_AUTHORITY_INVALID
,意思是頒發(fā)證書的 CA 機(jī)構(gòu)無效。
而現(xiàn)在錯(cuò)誤變成了 ERR_CERT_COMMON_NAME_INVALID
,這是什么意思呢?它其實(shí)是說證書的 CN
和我們?cè)L問的地址不匹配,怎么理解呢?還記得我們創(chuàng)建該證書的時(shí)候,里面包含了 CN=techcorner.cn
,意思是這個(gè)證書只能被 techcorner.cn
這個(gè)域名使用,現(xiàn)在我們?cè)L問的是 localhost
,顯然他們是不匹配的,因此證書無效。
雖然我們沒有購買該域名的使用權(quán)限,但是可以通過在本地修改 hosts 的方式,強(qiáng)行將 techcorner.cn
解析為本機(jī)地址 127.0.0.1
。
具體方式為,修改本機(jī)的 /etc/hosts
文件,在文件末尾增加一行
127.0.0.1 techcorner.cn
添加完畢后,再次使用瀏覽器訪問 https://techcorner.cn
可以發(fā)現(xiàn),Chrome 提示連接是安全的,證書是有效的
文章來源:http://www.zghlxwxcb.cn/news/detail-413506.html
Perfect,恭喜你,到這里,實(shí)戰(zhàn)部分就結(jié)束了,你已經(jīng)成功體驗(yàn)了 HTTPS 的全部內(nèi)容。文章來源地址http://www.zghlxwxcb.cn/news/detail-413506.html
到了這里,關(guān)于萬字長文,帶你徹底搞懂 HTTPS(文末附實(shí)戰(zhàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!