理解Https

之前的文章講golang webSocket編程的文章中提到過Http協議的概念,通過之前的瞭解我們也知道Http協議其實就是基於傳輸層的TCP協議和網絡層的IP協議實現的一個協議,所以他擁有TCP/IP的所有特性。也正是因爲它使用TCP/IP協議,導致它會有以下問題:

  • 通信使用明文,通信內容有可能會被竊聽
  • 不驗證通信方的身份,有可能遭遇僞裝
  • 通信內容可能遭到篡改

1. HTTP存在的風險

1.1 通信明文內容有可能會被竊聽

由於HTTP本身不具有加密功能,所以無法做到對HTTP協議通信的請求和相應內容進行加密,即HTTP報文只能使用明文方式發送。按照TCP/IP協議族的工作機制,通信的內容在所有的通信線路上都有可能遭到窺視。

所謂互聯網,是有連通到全世界的網絡組成的。無論世界哪個角落的服務器和客戶端通信時,在此通信線路上的某些網絡設備、光纜、計算機等都不可能是個人的私有物,所以不排除某個環節中遭到惡意窺視的行爲。

即使已經加密處理的通信,也會被窺視到通信內容,這點和未加密的通信是相同的。只是說如果通信經過加密,就有可能讓人無法破解原文信息的含義,但是加密處理後的報文信息本身還是會被看到。

竊聽相同段上的通信並非難事,只需要收集在互聯網上流動的數據包(幀)就行了。對於收集來的數據包的解析工作,可以交給那些抓包(Packet Capture、wireshark)或嗅探器(Sniffer)工具。

1.2 不驗證通信方的身份,可能遭遇僞裝

HTTP協議中的請求和響應不會對通信方進行確認,也就是說存在“服務器是否就是發送請求中URI真正指定的主機,返回的相應是否真的返回到實際提出請求的客戶端”等類似的問題。會存在以下隱患:

  • 無法確定請求發送至目標的web服務器是否是按照真實意圖返回響應的那臺服務器,有可能是已僞裝的web服務器。
  • 無法確定響應返回到的客戶端是否是按照真實意圖接收響應的那個客戶端,有可能是已僞裝的客戶端。

1.3 通信內容可能遭到篡改

上面講到HTTP報文是在網絡中裸奔的,有可能回被竊聽,並且通信雙方也無法確認對方的身份。那麼如果請求的服務器是僞裝的服務器或者報文傳輸過程中被中間節點篡改,客戶端也無法感知到。

比如,從某個web網站下載內容,客戶端是無法確認下載的文件和服務器上存放的文件是否一致的。文件傳輸途中有可能已經被篡改爲其他內容。即使內容已經被改變,客戶端瀏覽器也無法感知到。

雖然有使用HTTP協議確定報文完整性的方法,但事實上並不方便、可靠。其中常用的是MD5和SHA-1等散列值校驗方法,以及用來確認文件的數字簽名方法。但是這些方法只能保證HTTP報文是完整的,並無法保證報文是正確的。比如用戶想從某網站下載一張“秋香”的圖片,但是在傳輸過程中,內容被整體修改爲“如花”,並且數字簽名也重新生成了,那麼當報文到達客戶端瀏覽器時,瀏覽器依然會認爲報文是完整的,報文是否正確只能由本人確認。

爲了有效防止HTTP協議以上這些弊端,有必要使用HTTPS。其實HTTPS說白了就是HTTP + 加密 + 身份認證 + 報文正確性保障。

2. HTTPS協議

2.1 基礎概念

HTTPS,即超文本傳輸安全協議(HyperText Transfer Protocol Secure,也被稱爲HTTP over TLS、HTTP over SSL或HTTP Secure)是一種通過計算機網絡進行安全通信的傳輸協議。HTTPS經由HTTP進行通信,但利用SSL/TLS來加密數據包。HTTPS開發的主要目的,是提供對網站服務器的身份認證,保護交換數據的隱私與完整性。這個協議由網景公司(Netscape)在1994年首次提出,隨後擴展到互聯網上。

HTTPS的主要作用是在不安全的網絡上創建一個安全信道,並可在使用適當的加密包和服務器證書可被驗證且可被信任時,對竊聽和中間人攻擊提供合理的防護。

2.2 HTTP到HTTPS的演化過程

2.2.1 對稱加密

HTTP最大的問題在於報文的裸奔,如果可以把通信報文進行加密,那麼問題是不是就解決了?所以人們想到一個辦法:對傳輸的信息加密。而加密算法中最方便的就是對稱加密算法(加密和解密時使用相同的密鑰)。如下圖所示:

這種方式屬於對稱加密,雙方持有相同的密鑰,再第三方不知道加密密鑰的前提下信息可以安全傳輸,但此種方式的缺點是:

  • 不同的客戶端、服務器數量龐大,所以雙方都需要維護大量的密鑰,維護成本很高
  • 因每個客戶端、服務器的安全級別不同,密鑰極易泄露
  • 密鑰傳遞也是通過Http明文傳遞的,很有可能被窺探,使用密鑰加密的信息仍然可以被窺探、篡改

2.2.2 非對稱加密

使用對稱加密算法的問題在於,客戶端、服務端都需要維護密鑰,並且加密的密鑰不能保證得到安全傳輸,那有沒有一種辦法可以去掉加密的密鑰,並且仍然可以達到加密的效果。答案是存在的,就是非對稱加密,而非對稱加密一個典型的算法就是RSA算法。

非對稱加密算法不像之前的算法那樣,雙方必須協商一個保密的密鑰,而是有一對兒鑰匙, 一個是保密的,稱爲私鑰,另外一個是公開的,稱爲公鑰。用私鑰加密的數據,只有對應的公鑰才能解密,用公鑰加密的數據,只有對應的私鑰才能解密。

有了非對稱加密這兩個特性, 當客戶端給服務端發消息的時候, 就可以先用服務端的公鑰去加密(服務端的公鑰是公開的,所有人都知道), 等到消息被服務端收到後, 就可以用自己的私鑰去解密(只有服務端才能解開,私鑰是保密的 )

這個方式看起來是非常安全的,但是其實也存在問題:

  • 客戶端獲取服務端的公鑰是通過Http獲取的,存在被第三方篡改的可能,一旦客戶端拿到非服務端的公鑰,那麼之後的通信就都不是安全的了(這個問題後面再解釋)
  • 非對稱加密算法相比於對稱加密,速度非常慢,很影響通信效率

2.2.3 對稱加密 + 非對稱加密

回到最初的問題,最開始想用一個密鑰來加密通信,那個對稱加密算法是非常快的,但是苦於密鑰無法安全傳輸, 現在使用了非對稱加密算法,但是非對稱加密算法又效率又非常低。那麼是否可以將上述兩種算法結合一下, 分兩步走:

  1. 服務端生成一個對稱加密算法的密鑰, 用非對稱加密算法的方式安全發給客戶端
  2. 服務端客戶端隨後就不用非對稱加密算法了, 只用這個密鑰,利用對稱加密算法來通信

這樣既解決了對稱加密算法密鑰無法安全傳輸,又解決了非對稱加密算法效率低下的問題。看起來很完美,但是仍然是存在問題的,就是之前講非對稱加密的問題1,我們來分析一下。

假如,服務端給客戶端發送公鑰的時候, 有個中間人,截取了服務端的公鑰, 然後把自己的公鑰發給客戶端,冒充服務端,客戶端發的消息就是用中間人的公鑰加密的,那中間人不就可以解密看到消息了?同時客戶端還可以將自己篡改的消息使用真正服務端的公鑰加密,發送給服務端。這個過程中,客戶端服務端都是無法感知這個中間人的存在的。

 現在看來,使用對稱加密 + 非對稱加密的方式,實可以解決單獨使用對稱加密或單獨使用非對稱加密的問題,但是仍有一個問題沒法解決,那就是客戶端無法保證自己收到的公鑰來自真正的服務端

2.2.4 對稱加密 + 非對稱加密 + 證書

使用對稱加密 + 非對稱加密的方式後,問題就在於怎麼安全的分發公鑰,即想辦法聲明公鑰是來自真正的服務端,而不是別人冒充的。生活中,我們肯定知道公證處的概念,它提供的公正材料大家都信任,那麼網絡世界是否也可以建立一個這樣具備公信力的認證中心,這個中心給服務端頒發一個證書,用於證明服務端的身份。而證書中除了包含服務端的基本信息之外,還包含一個最關鍵的內容:服務端的公鑰。這樣客戶端就可以安全地拿到服務端的公鑰了。然而理想很豐滿,現實很骨感。證書怎麼安全傳輸,如果證書傳輸過程中被篡改了怎麼辦?所以還需要一些額外的輔助驗證措施,那就是數字簽名

簡單來講就是, 服務端可以把他的公鑰和基本信息用一個Hash算法生成一個消息摘要, 這個Hash算法有個極好的特性,只要輸入數據有一點點變化,那生成的消息摘要就會有鉅變,這樣就可以防止別人修改原始內容。

這種數字簽名的方式,雖然第三方沒辦法改公鑰,但是卻可以把整個原始信息都替換了, 生成一個新的消息摘要, 這樣客戶端還是辨別不出來。爲了解決這個問題,那就只能藉助公證處再幫忙對消息摘要做個加密,如下:

讓有公信力的認證中心(簡稱CA)用它的私鑰對消息摘要加密,形成簽名,然後原始信息和數據簽名合併, 形成一個全新的東西,叫做“數字證書”。這樣即使第三方替換原始信息,也因爲不知道CA的私鑰,而無法僞造證書。

當服務端把他的證書發給客戶端的時候, 客戶端就用同樣的Hash算法, 再次生成消息摘要,然後用CA的公鑰對數字簽名解密, 得到CA創建的消息摘要, 兩者一比,就知道有沒有人篡改了!如果沒人篡改, 客戶端就可以安全的拿到服務端的公鑰,有了公鑰, 客戶端就可以使用這個公鑰加密一個隨機數(隨機數就是之後對稱加密的密鑰)發給服務端,之後雙方就通過這個隨機數使用對稱加密通信。

到這,看似解決了問題,但是仔細一想,如果在客戶端在獲取CA公鑰時,CA公鑰被替換,第三方僞裝成CA,這樣後續的操作還是不安全的。完全就是雞生蛋、蛋生雞的問題,如果要跳出這個怪圈,就必須信任CA,並通過安全的方式獲取他們的公鑰。

這些CA本身也有證書來證明自己的身份,並且CA的信用是像樹一樣分級的,高層的CA可以證明底層CA的可靠性,而操作系統/瀏覽器中會內置一些頂層的CA的證書,相當於你自動信任了他們。所以可以認爲客戶端可以安全的拿到CA的公鑰,那麼也就不存在第三方僞裝成CA的情況了。

我們再回顧一下之前的一個概念,HTTPS = HTTP + 加密 + 身份認證 + 報文正確性保障。

  • HTTP:HTTPS其實就是安全的HTTP,傳輸層使用的TCP協議,網絡層使用的IP協議。因爲使用TCP協議,所以建立連接也需要進行TCP的三次握手、斷開連接也需要四次揮手。與HTTP不同的是,因爲HTTPS要保證報文安全傳輸,就是上面講的使用對稱加密 + 非對稱加密結合的方式,所以可以進行報文傳輸的前提除了TCP的三次握手之外,還需要已經交換了對稱加密的密鑰,這個交換對稱加密密鑰的過程就是SSL握手,所以HTTPS連接 = TCP連接 + SSL連接,這就是爲什麼HTTPS比HTTP要慢的原因之一。
  • 加密:HTTPS是安全的報文傳輸協議,所謂安全,就是使用對稱加密方式對報文進行了加密。
  • 身份認證:上面講到,HTTPS可以進行報文傳輸的前提是TCP連接 + SSL連接,其實SSL連接就可以理解爲客戶端和服務端建立了安全的傳輸通道,其實就是雙方安全地交換了之後報文對稱加密的密鑰。這個過程設計客戶端對證書的驗證,證書驗證通過,就可以說明服務端是整整訪問的服務端,而非僞造的。
  • 報文正確性保障:因爲雙方的通信是通過約定的安全密鑰,使用對稱加密算法加密的。所以不存在被篡改的可能。比如第三方即使抓取了報文,但是因爲不知道密鑰,也不能篡改報文信息。這樣就能保證我們下載的“秋香”肯定是“秋香”,而不會被第三方惡意篡改爲“如花”。

最後用一個簡化的HTTPS流程圖來總結一下HTTPS訪問流程, 如果你理解了前面的原理,這張圖就變得非常簡單:

參考鏈接:

1. 《碼農翻身》

2. 《圖解HTTP》

3. 維基百科——超文本傳輸安全協議

4. 維基百科——傳輸層安全協議(SSL)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章