1. 程式人生 > >我終於搞清了啥是 HTTPS 了

我終於搞清了啥是 HTTPS 了

![](https://cdn.geekdigging.com/technique-sharing/20200530/http-vs-https.jpg) ## 引言 最近上海連續下了一週雨,溫度一夜之間回到解放前,穿夏裝的我被凍得瑟瑟發抖,躲在家裡哪也不想去。 ![](https://cdn.geekdigging.com/technique-sharing/20200530/sesefadou.gif) 在家百無聊賴的刷著網頁,看到公眾號後臺的留言,有同學問我 HTTP 和 HTTPS 有啥區別? 這還用問,當然是 HTTPS 要比 HTTP 更加的安全啊,沒看到後面帶著個 S 呢麼,帶著 S 就這麼 NB 。 然後同學的下一個問題把我問懵逼了,為啥帶 S 的更安全呢?能詳細的講講麼。 我跟你講嗷,不是我吹,我這麼多年。。。。。。 就沒見過你這麼刨根究底的同學,老問這種我也不是很清楚的問題。 雖然這個問題問的我老臉一紅,但是我有一種不要臉的精神 「我不會,但是我可以學」 。 ![](https://cdn.geekdigging.com/technique-sharing/20200530/liaobuqi.gif) ## HTTP 首先先來了解下 HTTP : HTTP 協議全稱為:Hyper Text Transfer Protocol ,翻譯過來就是超文字傳輸協議,請不要質疑這個翻譯,我專門用百度翻譯翻了一下。 TCP/IP 四層模型應該都知道的,有資料鏈路層,網路層,傳輸層和應用層: ![](https://cdn.geekdigging.com/technique-sharing/20200530/tcpip.png) 而 HTTP 協議就是位於 TCP/IP 四層模型的應用層上。 ![](https://cdn.geekdigging.com/technique-sharing/20200530/tcpip_1.png) 這裡很多人都會混淆 TCP 和 HTTP ,實際上 HTTP 是基於 TCP 連線基礎上的。 簡單的說, TCP 就是單純建立連線,不涉及任何我們需要請求的實際資料,簡單的傳輸。而 HTTP 是用來收發資料,即實際應用上來的。 HTTP 協議通過請求和響應在客戶端和服務端之間收發資料,進行通訊: ![](https://cdn.geekdigging.com/technique-sharing/20200530/request-response.png) ## HTTPS HTTP 協議看起來好像沒啥問題,唯一的問題就是不夠安全,因為 HTTP 協議的傳輸方式完全是由明文傳輸的,不做任何加密,這就讓一些不懷好意的人有了可乘之機。 這種傳輸方式誘發了一種經典的攻擊方式:中間人攻擊。 ![](https://cdn.geekdigging.com/technique-sharing/20200530/zhongjianrengongji_1.png) 對於這種情況,最簡單的我們可以使用加密方案,比如使用 AES 加密,服務端和客戶端先約定一個隨機生成的金鑰 key ,後續的通訊中,所有的資訊都使用這個金鑰進行 AES 加密: ![](https://cdn.geekdigging.com/technique-sharing/20200530/zhongjianrengongji_2.png) 這樣雖然後面的通訊過程安全了,但是我們在第一發送 AES 金鑰的時候還是存在被中間人攔截的風險,一旦中間人攔截到我們的金鑰,可用對金鑰進行更換或者直接解密請求內容: ![](https://cdn.geekdigging.com/technique-sharing/20200530/zhongjianrengongji_3.png) 這時我們可以使用不對稱加密,來專門對金鑰的傳輸做一次額外的保護。 不對稱加密會有兩個金鑰,一個是公鑰,一個是私鑰。明文可以使用公鑰加密私鑰解密,也可以使用私鑰加密公鑰解密。 現在比較通用的非對稱加密演算法有 RSA 。 ![](https://cdn.geekdigging.com/technique-sharing/20200530/zhongjianrengongji_4.png) 看到這裡的同學一定在奇怪,既然都使用了不對稱加密,為啥只對 AES 的金鑰做不對稱加密,好像有多此一舉,完全可以對後續所有的通訊資訊全都使用不對稱加密。 因為不對稱加密相比較對稱加密效能上存在明顯的劣勢,可能你覺得在一個請求中多消耗幾 ms 或者幾 ns 無所謂,但是請求到達服務端是要進行解密,每個請求都多消耗幾 ms 累計起來還是非常可觀的。 上面這個方案看起來已經很安全了,中間人即使攔截到我們的公鑰,由於不知道我們的私鑰貌似也沒辦法解密。 實際上中間人完全不需要解密我們的資訊,他可以生成一對新的公私鑰傳送給客戶端進行攻擊,後續客戶端的通訊中間人使用自己創造的私鑰進行解密,然後通過服務端生成的公鑰進行加密返回給服務端: ![](https://cdn.geekdigging.com/technique-sharing/20200530/zhongjianrengongji_5.png) ## CA 證書 上面的問題我們僅通過客戶端和服務端已經沒辦法了,這時候需要引入新的第三方機構,一個頒發 CA 證書的機構。 常見的第三方 CA 機構有:Symantec(賽門鐵克),Comodo(科莫多),GeoTrust(環度網信),GoDaddy,Thawte,daoRapidSSL 等等。 在中間人攻擊中,我們遇到的問題不是加密演算法不夠神奇,不是金鑰方式不夠嚴謹,而是我們沒有辦法向我們的客戶端表明我們給他的公鑰是我們的,是不是很像我沒辦法證明我是我的問題。 ![](https://cdn.geekdigging.com/technique-sharing/20200530/qingzhengming.jpg) 所以第三方機構應運而生,第三方機構只做一件事情,將服務端的公鑰刻上了我們的名字(CA 證書),客戶端接收到公鑰之後,只需要來第三方機構這裡查詢,就能知道這個公鑰是不是真的伺服器,然後再將自己生成的 AES 金鑰使用 CA 證書中解密得到的公鑰進行加密後傳送給服務端。 ![](https://cdn.geekdigging.com/technique-sharing/20200530/zhongjianrengongji_6.png) 最後服務端使用私鑰解密得到 AES 金鑰,就可以愉快的和客戶端進行通訊了。 最後的最後,CA 機構驗證不是每次都要去 CA 機構查詢。這樣做太傻了而且太耗時,尤其是很多 CA 機構的服務都在海外,這樣一來一去消耗的時間太多了。 CA 機構高明的地方就在於,我們去找它註冊公鑰,它會使用另一個來註冊的公司的私鑰對我們的公鑰加密,得到一個我們的公鑰的指紋(全球唯一),然後將這家公司的公鑰資訊(其實也是證書)和我們的公鑰以及我們公鑰的指紋打包成一個證書。 當我們使用 HTTPS 將證書下發給客戶端校驗時,客戶端(比如瀏覽器)從證書中看到了上級證書的資訊,恰巧這個證書就在瀏覽器(或者本機)中,已經被驗證過是合法的,瀏覽器只要使用這個證書中的公鑰將我們的公鑰指紋進行解密,然後比對我們的公鑰資訊就知道我們也是的合法的。因為假證書中的公鑰簽名不可能被合法的上級證書中公鑰解密 。 這段稍微有點繞,慢慢看多看幾次就理解了。 ## 參考 https://www.jianshu.com/p/691b8ba3a70f https://blog.csdn.net/u010144805/article/details/80803059 https://blog.csdn.net/caofengtao1314/article/details/87912078