1. 程式人生 > >熟悉又陌生的HTTPS

熟悉又陌生的HTTPS

歡迎大家加入QQ群一起討論: 489873144(android格調小窩)

全文較長,主要從概覽,到原理,到抓包整個流程進行全方位的解讀,個人能力有限,我也是通過在網上尋找資料,結合自己的理解整理出來的,如有不當,歡迎指正。

如果你認真看完本文,以下幾個問題你將會有答案:

  1. 什麼是Https,為什麼要使用Https,SSL/TLS 協議又是什麼
  2. 什麼是對稱加密、非對稱加密,各自的優缺點
  3. 什麼是中間人攻擊,Https的加密方案是什麼,如何防止中間人攻擊
  4. 什麼是CA、證書、證書鏈,證書如何吊銷
  5. 數字簽名又是什麼,與證書什麼關係
  6. TLS/SSL 如何握手,以及握手傳遞的引數
  7. 什麼是單向認證、雙向認證,有什麼區別
  8. 什麼是自簽名證書,如何認證自簽名證書,自簽名證書安全嗎
  9. Https對效能的損耗有多大,如何優化
  10. Https如何抓包,抓包的資料如何看懂是什麼意思

一、HTTPS的概念

首先為什麼使用Https呢,這個問題回答前,我們需要對現在使用的http協議有了解。

http日常使用極為廣泛的協議,它很優秀且方便,但還是存在一些問題,如:
- 明文通訊,內容可以直接被竊聽:HTTP 不會對請求和響應的內容進行加密,報文直接使用明文傳送,沒有經過任何安全處理。報文在伺服器與客戶端流轉中間,會經過若干個結點,這些結點中隨時都可能會有竊聽行為。例如使用者在百度搜索了一個關鍵字,比如“微辦公”,攻擊者想要做些什麼並沒有任何的限制,包括竊取使用者的Session資訊。
- 無法驗證報文的完整性,可能被篡改

:攻擊者在竊聽的同時還可以注入有害的程式碼等,乃至於修改使用者傳送至伺服器的資料。因為通訊一定會經過中間很多個結點,所以就算是報文經過了加密,也一樣會被竊聽到,不過是竊聽到加密後的內容,而雙方是無法知道這個資訊是否被篡改的。
- 通訊方身份不驗證:可能遇到假的客戶端或伺服器,這個就是我們說的通訊中間會經過很多節點,而隨便增加一個或減少一個,通訊都是可以完成,沒有驗證機制。

這裡提到的攻擊者或者中間者主要指一些網路節點,是使用者資料在瀏覽器和伺服器中間傳輸必須要經過的節點。比如 WIFI 熱點,路由器,防火牆,反向代理,快取伺服器等。

那麼https 能否解決以上問題呢,答案是可以的。

HTTPS = HTTP + 加密 + 認證 + 完整性保護

(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標的HTTP通道,簡單講是HTTP的安全版。是在HTTP基礎上加入網景公司設計的SSL層,HTTPS的安全基礎是SSL,因此需要加密就需要SSL。

SSL:(Secure Socket Layer,安全套接字層),位於可靠的面向連線的網路層協議和應用層協議之間的一種協議層。
TLS:(Transport Layer Security,傳輸層安全協議),用於兩個應用程式之間提供保密性和資料完整性。

TLS 是傳輸層加密協議,它的前身是 SSL3.0 協議,最早由 netscape 公司於 1995 年釋出,1999 年經過 IETF 討論和規範後,改名為 TLS。如果沒有特別說明,SSL 和 TLS 說的都是同一個協議。

目前有以下幾個版本:SSLv2,SSLv3,TLSv1,TLSv1.1,TLSv1.2,當前基本不再使用低於 TLSv1 的版本;

二、 TLS/SSL協議的基本概念

TLS/SSL在協議中的位置如下,屬於傳輸層之上,應用層之下的一箇中間協議。

TLS/SSL的完成加密功能的核心是密碼學原理,而加密就是保護資料安全的措施。一般是利用技術手段把有效資料變成亂碼(加密)傳送,到達目的地後,再利用對應的技術手段還原資料(解密)。加密包含演算法和金鑰兩個元素。演算法將要加密的資料與金鑰(一串數字)相結合,產生不可理解的密文。由此可見,金鑰與演算法同樣重要。

現在的加密方法中,加密演算法都是公開的,網上都有各種演算法原理解析的內容。加密演算法雖然是公開的,演算法用到的金鑰卻是保密的,以此來保持加密方法的安全性。加密和解密都會用到金鑰。有了金鑰就可以解密了,如果金鑰被攻擊者獲得,加密也就沒有意義了。

上面的圖展示了TLS/SSL協議為了解決http協議在安全性方面的不足,對資料加密使用了三類基本演算法,具體介紹如下,我們先從簡單的開始說:

1. 雜湊函式Hash,驗證資訊的完整性

這個大家應該經常使用,比如下載一個檔案,如何保證我下載的檔案就是沒有沒篡改的,是不是完整的,那麼我們就檢驗一下檔案的MD5值,所以該類演算法常見的有* MD5、SHA1、SHA256*,該類函式特點是函式單向不可逆、對輸入非常敏感、輸出長度固定,針對資料的任何修改都會改變雜湊函式的結果,用於防止資訊篡改並驗證資料的完整性;
md5破解線上查詢

2. 對稱加密,採用協商的金鑰對資料進行對稱加密

對稱加密的意思就是,加密資料用的金鑰,跟解密資料用的金鑰是一樣的。常見的有AES-CBC、DES、3DES、AES-GCM等,掌握金鑰才能獲取資訊,能夠防止資訊竊聽,通訊方式是1對1;

  • 優點:

    • 對稱內容加密強度非常高,一般破解不了
    • 加解密速度快,效能開銷小,一次完全的 TLS 握手,金鑰交換時的非對稱解密計算量佔整個握手過程的 90% 以上。而對稱加密的計算量只相當於非對稱加密的 0.1%,
  • 缺點:

    • 要求提供一條安全的通道使通訊雙方在首次通訊時協商一個共同的金鑰。直接面對面協商可能難於實施,所以雙方需要藉助於郵件和電話等其他相對不夠安全的手段來進行協商。
    • 金鑰的數目難於管理。因為對於每一個合作者都需要使用不同的金鑰,很難適應開放社 會中大量的資訊交流。
    • 對稱加密演算法一般不能提供資訊完整性的鑑別。它無法驗證傳送者和接受者的身份。
    • 對稱金鑰的管理和分發工作是一件具有潛在危險的、繁瑣的過程。對稱加密是基於共同保守祕密來實現的,採用對稱加密技術的貿易雙方必須保證採用的是相同的金鑰,保證彼此金鑰的交換是安全可靠的,同時還要設定防止密匍洩密和更改金鑰的程式。

3. 非對稱加密,實現身份認證和金鑰協商,

即常見的RSA、ECDHE、DH 、DHE等演算法,演算法特點是,金鑰成對出現,一般稱為公鑰(公開)和私鑰(保密),公鑰加密的資訊只能私鑰解開,私鑰加密的資訊只能公鑰解開。因此掌握公鑰的不同客戶端之間不能互相解密資訊,只能和掌握私鑰的伺服器進行加密通訊,伺服器可以實現1對多的通訊,客戶端也可以用來驗證掌握私鑰的伺服器身份。

  • RSA:演算法實現簡單,誕生於 1977 年,歷史悠久,經過了長時間的破解測試,安全性高。其數學原理是將一個大數分解成兩個質數的乘積,加密和解密用的是兩個不同的金鑰。即使己知明文、密文和加密金鑰(公鑰),想要推匯出解密金鑰(私鑰),在計算上是不可能的。按現在的計算機技術水平,要破解目前採用的1024位RSA金鑰,需要上千年的計算時間。在2010年以後,均採用了2048位的簽名。RSA 是目前唯一一個既能用於金鑰交換又能用於證書籤名的演算法。缺點就是需要比較大的素數(目前常用的是 2048 位)來保證安全強度,很消耗 CPU 運算資源。
  • DH:diffie-hellman 金鑰交換演算法,誕生時間比較早(1977 年),但是 1999 年才公開。缺點是比較消耗 CPU 效能。
  • ECDHE:使用橢圓曲線(ECC)的 DH 演算法,優點是能用較小的素數(256 位)實現 RSA 相同的安全等級。缺點是演算法實現複雜,用於金鑰交換的歷史不長,沒有經過長時間的安全攻擊測試。
  • ECDH:不支援 PFS,安全性低,同時無法實現 false start。
  • DHE:不支援 ECC。非常消耗 CPU 資源。

那麼總結非對稱加密的優點就是:使用者可以公開其公鑰,而保留私鑰,就算別人知道了公鑰也無法解密資料,還可以1對N通訊,缺點也很明顯,極度的消耗cpu的資源,就像前文說的,一次完全 TLS 握手,金鑰交換時的非對稱解密計算量佔整個握手過程的 90% 以上。而對稱加密的計算量只相當於非對稱加密的 0.1%,如果應用層資料也使用非對稱加解密,效能開銷太大,無法承受。

三、中間人攻擊和資訊抵賴

我們前面講到了TLS/SSL協議使用了三種加密演算法確保了資料的完整性、有效性,那麼是不是就夠了呢?我們來看如下場景。

身份驗證和金鑰協商是TLS的基礎功能,要求的前提是合法的伺服器掌握著對應的私鑰。但RSA演算法無法確保伺服器身份的合法性,因為公鑰並不包含伺服器的資訊。

上面這句話不好理解,我們看下圖:

假如我是攻擊者,也就是中間人M,現在開始攻擊,步驟如下:

  1. 客戶端C和伺服器S進行通訊,中間節點M截獲了二者的通訊,也就是路由器節點,代理伺服器等等,反正你不可能直接和伺服器通訊;
  2. 節點M自己計算產生一對公鑰pub_M和私鑰pri_M
  3. C要對資料進行加密,那麼一定需要先知道加密的金鑰是什麼,於是向S請求,讓S把加密的公鑰給C
  4. C向S請求公鑰的過程中,M可以截獲請求,於是把自己的公鑰pub_M發給了C;
  5. C拿到這個pub_M後,是無法知道這個公鑰是M給的還是S給的,因為公鑰中沒有包含伺服器的資訊。
  6. 於是C使用公鑰pub_M把資料加密後發出去;
  7. M再次攔截,因為資料是用pub_M加密的,而解密的私鑰pri_M自己擁有,所以M解密C發出去的資料,拿到明文;
  8. M在拿到明文後,使用S返回的公鑰pub_S再次加密明文,傳送給S;
  9. S拿到了被自己的公鑰pub_S加密後的密文,當然也能用自己的pri_S解密,但是S同樣無法知道這個請求是M發出的,因為請求的資訊中沒有包含客戶端的任何資訊。
  10. S接著對客戶端C進行響應,M再次攔截,步驟與請求一樣;

這樣就完成了一次攻擊,客戶端C與服務端S通訊的所有內容被中間人M全部獲取,但是C和S無法感知到M的存在,雙方都沒有機制去判斷對方的身份是否可信。此外M除了對進行竊聽外,還可以進行篡改等操作,雙方依然是無法感知的。這也就導致了伺服器同樣也可以對自己的發出的資訊進行否認,不承認相關資訊是自己發出,這也就是資訊抵賴。

四、身份驗證CA和證書

那麼既然這樣都無法解決通訊的安全問題,怎麼辦呢?這時候跳出來了一個人,他就是CA機構(Certification Authority 數字證書認證機構),他是具有權威性、公正性的機構,他說,我來負責對你們的身份進行認證,具體怎麼做呢,看下面:

基本的原理為,CA負責稽核資訊,然後對關鍵資訊利用私鑰進行”簽名”,公開對應的公鑰,客戶端可以利用公鑰驗證簽名。CA也可以吊銷已經簽發的證書,具體的流程如下:

  1. 服務端生成一對公私鑰,服務端自己保留私鑰key,利用公鑰加上公司資訊,伺服器資訊生成請求檔案csr;
  2. 用生成的csr檔案向國際CA機構提交申請,CA稽核通過後,會為申請者頒發一個數字證書,一般是cer或者crt檔案,並且CA會用自己的私鑰對提交的資訊進行簽名,並將該簽名附加在證書上
  3. CA將生成好的證書頒發給申請者,這樣服務端就是一個被CA認可的可信伺服器。
  4. 以後客戶端在請求伺服器的時候,伺服器會直接將證書返回給客戶端
  5. 客戶端拿到這個證書後,會驗證簽名是否合法,那麼如何驗證這個簽名呢,這個簽名是被CA用他自己的私鑰加密的,所以我們只需要用CA的公鑰去解密。那麼這個公鑰要去哪裡弄呢,實際上常用的認證機構的公鑰證書都會被內建在手機、電腦、瀏覽器中,大概有150-200個證書被內建。位置如下:

在這個過程需要理解以下幾點:

  1. 申請證書不需要提供私鑰,確保私鑰永遠只能伺服器掌握;
  2. 證書的合法性仍然依賴於非對稱加密演算法,證書主要是增加了伺服器資訊以及簽名;
  3. 內建 CA 對應的證書稱為根證書,頒發者和使用者相同,自己為自己簽名,即自簽名證書;
  4. 證書=公鑰+申請者與頒發者資訊+簽名;
  5. 公鑰放在數字證書中。只要證書是可信的,公鑰就是可信的。

那麼一個真實的證書是什麼樣呢?如下所示,開啟chrome瀏覽器,輸入一個https的站點,比如我們公司微辦公的首頁https://www.weibangong.com,或者百度的首頁都可以,這裡我們用我們公司的示例,點選瀏覽器上的這把小綠鎖,

然後點選這個檢視證書的按鈕

我們會看到如下結果

這個裡面包含了公司和伺服器還有加密公鑰,加密演算法,數字簽名等很多重要資訊。

五、證書鏈

證書鏈:伺服器證書、中間證書與根證書在一起組合成一條合法的證書鏈,證書鏈的驗證是自下而上的信任傳遞的過程,原理圖如下:

我們公司的證書結構如下:

即CA根證書和伺服器證書中間增加一級證書機構,即中間證書,證書的產生和驗證原理不變,只是增加一層驗證,只要最後能夠被任何信任的CA根證書驗證合法即可。

  • 伺服器證書 server.pem 的簽發者為中間證書機構 inter,inter 根據證書 inter.pem 驗證 server.pem 確實為自己簽發的有效證書;
  • 中間證書 inter.pem 的簽發 CA 為 root,root 根據證書 root.pem 驗證 inter.pem 為自己簽發的合法證書;
  • 客戶端內建信任 CA 的 root.pem 證書,因此伺服器證書 server.pem 的被信任。

使用證書鏈具有以下好處:

  1. 減少根證書結構的管理工作量,可以更高效的進行證書的稽核與簽發;
  2. 根證書一般內建在客戶端中,私鑰一般離線儲存,一旦私鑰洩露,則吊銷過程非常困難,無法及時補救;
  3. 中間證書結構的私鑰洩露,則可以快速線上吊銷,並重新為使用者簽發新的證書;
  4. 證書鏈四級以內一般不會對 HTTPS 的效能造成明顯影響。

同時證書鏈還有以下特點:

  1. 同一本伺服器證書可能存在多條合法的證書鏈。因為證書的生成和驗證基礎是公鑰和私鑰對,如果採用相同的公鑰和私鑰生成不同的中間證書,針對被簽發者而言,該簽發機構都是合法的 CA,不同的是中間證書的簽發機構不同;
  2. 不同證書鏈的層級不一定相同,可能二級、三級或四級證書鏈。中間證書的簽發機構可能是根證書機構也可能是另一箇中間證書機構,所以證書鏈層級不一定相同。

六、證書吊銷

CA 機構能夠簽發證書,同樣也存在機制宣佈以往簽發的證書無效。證書使用者不合法,CA 需要廢棄該證書;或者私鑰丟失,使用者申請讓證書無效。主要存在兩類機制:CRL 與 OCSP。

CRL

Certificate Revocation List, 證書吊銷列表,是一個單獨的檔案。該檔案包含了 CA 已經吊銷的證書序列號(唯一)與吊銷日期,同時該檔案包含生效日期並通知下次更新該檔案的時間,當然該檔案必然包含 CA 私鑰的簽名以驗證檔案的合法性。

對於一個證書的實際欄位如下:

在證書中一般會包含一個 URL 地址 CRL Distribution Point,通知使用者去哪裡下載對應的 CRL 以校驗證書是否吊銷。該吊銷方式的優點是不需要頻繁更新,但是不能及時吊銷證書,因為 CRL 更新時間一般是幾天,這期間可能已經造成了極大損失。

OCSP

Online Certificate Status Protocol, 證書狀態線上查詢協議,一個實時查詢證書是否吊銷的方式。請求者傳送證書的資訊並請求查詢,伺服器返回正常、吊銷或未知中的任何一個狀態。

對於一個證書的實際欄位如下:

證書中一般也會包含一個 OCSP 的 URL 地址,要求查詢伺服器具有良好的效能。部分 CA 或大部分的自籤 CA (根證書)都是未提供 CRL 或 OCSP 地址的,對於吊銷證書會是一件非常麻煩的事情。

七、TLS/SSL握手過程

好講了這麼多,終於到了這篇文章的最核心的地方,在講握手之前,我們把前面關於握手有關的東西重新整理下,我們能得到如下結論,這幾個結論非常重要非常重要非常重要

  1. TLS/SSL使用了三種密碼學的演算法保證資料的有效性、完整性、安全性。
  2. 鑑於非對稱加密演算法極度消耗cpu的特點,最後的方案是,僅僅使用非對稱加密傳輸協商金鑰,真正的資料使用協商金鑰進行對稱加密,這樣既保證了安全性,也保證了效率。
  3. 但是這樣由於沒有資訊的驗證機制,所以這個任務交給了CA機構,於是TLS/SSL協議就誕生了。

好,有了上面的這個結論,我們再來詳細的看握手過程,看看每次握手究竟傳遞了什麼引數,服務端與客戶端是如何完成通訊的,那麼為了能夠看到傳遞的資料,我們需要對請求進行抓包,我們使用的工具是wireshake,使用他的原因是,TLS/SSL協議位於應用層之下,普通的fiddlercharles這兩個抓包工具只能抓應用層的資料,抓不到底層的資料,關於這個wireshake工具的下載地址,我這就不提供了,他是一個跨平臺的免費工具,mac和windows都有。

使用簡單說一句,開啟wireshake,選擇好網絡卡,在過濾條件中輸入ssl,然後開啟瀏覽器,進入百度主頁,就完成了,我們可以在wireshake的過濾資訊中找到符合如下,主要是右邊的info一欄,一定要看是這個順序的,一點都不能錯,否則就不好分析了。

所有的準備工作完畢,我們先上一張整個握手過程的大圖,如下,這個圖我也是來來回回畫了很久,很詳細,如果圖片看不清可以點選這裡檢視大圖。不要被這個圖嚇著了,如果你不願意自己看,那麼我們接下來一點點幫你分析,這個圖就是讓你有個整體印象。

1. Client Hello

前面我們抓包看到了,第一步是Client Hello,也就是客戶端向服務端傳遞一些客戶端的資訊,但是這個是明文傳輸,那麼我們點開Client Hello 看看裡面的資料:

  1. 支援的最高TLS協議版本號version,比如TLSv1.2(0x0303)。
  2. 一個客戶端生成的隨機數Random,這個隨機數一方面需要在客戶端儲存,另一方面需要傳送給服務端,客戶端的隨機數需要跟服務端產生的隨機數結合起來產生後面要講到的Master Secret。
  3. 支援的加密套件cipher suite列表,客戶端(如不同瀏覽器或手機)對一些加解密演算法的支援程度不一樣,但是在TLS協議傳輸過程中必須使用同一套加解密演算法才能保證資料能夠正常的加解密。在TLS 握手階段,客戶端首先要告知服務端,自己支援哪些加密演算法,所以客戶端需要將本地支援的加密套件(Cipher Suite)的列表傳送給服務端。詳細看圖,客戶端共計支援19種加密套件:
  4. 支援的壓縮方法compression methods 列表,用於後續的資訊壓縮傳輸,當前我們這個沒有壓縮。
  5. session ID 如果存在就會攜帶。

注意:客戶端傳送的資訊之中不包括伺服器的域名。也就是說,理論上伺服器只能包含一個網站,否則會分不清應該向客戶端提供哪一個網站的數字證書。這就是為什麼通常一臺伺服器只能有一張數字證書的原因。對於虛擬主機的使用者來說,這當然很不方便。2006年,TLS協議加入了一個Server Name Indication擴充套件,允許客戶端向伺服器提供它所請求的域名,如下:

補充:我們第一次看這種資料就先介紹一下這個結構,我們看到了下面顯示很多資料的框框,裡面分了五層,這五層分別是:

序號 描述
1 Frame 物理層
2 Ethernet 資料鏈路層
3 Internet Protocol IP網路層
4 Transmission Control Protocol TCP傳輸層
5 Secure Sockets Layer SSL安全套接層

如果你瞭解http協議,那麼你一定知道這就是經典的五層因特網協議棧,準確來說,SSL不屬於應用層,在SSL之上還有一層那就是HTTP應用層協議。

知道這個後,我們再看上圖裡面有兩列IP地址,Source和Destination,分別表示客戶端IP和服務端IP,很明顯,我的客戶端公網IP就是192.168.1.109,而61.135.169.121,我們可以直接ping一下百度的首頁就知道,這個是百度伺服器的IP,但是百度是叢集伺服器,有很多負載節點,所以不同地方ping的結果可能最後一位ip略有差異,這個不影響。

2. Server Hello

從Server Hello到Server Done,有些服務端的實現是每條單獨傳送,有服務端實現是合併到一起傳送。Sever Hello和Server Done都是隻有頭沒有內容的資料,我們的例子中就是每條單獨發,我們看Info中的Server Hello 和 Certificate 的IP,都是從服務端到客戶端的響應。

服務端在接收到客戶端的Client Hello之後,先儲存下客戶端傳送的隨機數,然後向客戶端返回協商的資訊結果(server_hello),也是明文傳輸,詳細資訊如下:
1. 確認使用的加密通訊協議版本version,比如TLS 1.2版本。
2. 跟客戶端一樣,服務端也需要產生一個隨機數傳送給客戶端。客戶端和服務端都需要使用這兩個隨機數來產生Master Secret。
3. 確認使用的加密套件Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
4. 選擇的壓縮演算法Compression Method: null (0)

此外,服務端需要將自己的證書傳送給客戶端。這個證書是對於服務端的一種認證。例如,客戶端收到了一個來自於稱自己是www.alipay.com的資料,但是如何證明對方是合法的alipay支付寶呢?這就是證書的作用,支付寶的證書可以證明它是alipay,而不是 財付通。證書是需要申請,並由專門的數字證書認證機構(CA)通過非常嚴格的稽核之後頒發的電子證書。頒發證書的同時會產生一個私鑰和公鑰。私鑰由服務端 自己儲存,不可洩漏。公鑰則是附帶在證書的資訊中,可以公開的。證書本身也附帶一個證書電子簽名,這個簽名用來驗證證書的完整性和真實性,可以防止證書被串改。另外,證書還有個有效期。

服務端繼續返回以下資料:
5. 伺服器證書鏈server_certificates,我們看到了總大小是2890位元組。
7. 在服務端向客戶端傳送的證書中沒有提供足夠的資訊的時候,還可以向客戶端傳送一個Server Key Exchange。 這是個非常重要的保密資料,以後服務端還需要對客戶端進行驗證,以保證資料傳送給了安全的合法的客戶端。
8. 服務端可以向客戶端發出Cerficate Request訊息,要求客戶端傳送證書對客戶端的合法性進行驗證。比如,金融機構往往只允許認證客戶連入自己的網路,就會向正式客戶提供USB金鑰,裡面就包含了一張客戶端證書。(這一步可省略,這一步就是要求下次請求的時候,客戶端需要帶上自己的證書,伺服器需要驗證客戶端的合法性,也就是雙向認證,我只是請求百度,只用到了單向認證)
9. 最後服務端會發送一個Server Hello Done訊息給客戶端,表示Server Hello訊息結束了。

補充

關於Cipher最後返回的的這一長串名字是什麼含義呢?其實,每種Cipher的名字裡包含了四部分資訊,分別是:

  1. 金鑰交換演算法 KeyExchange(金鑰協商),用於決定客戶端與伺服器之間在握手的過程中如何認證,用到的演算法包括RSA,Diffie-Hellman,ECDH,PSK等
  2. 對稱加密演算法 Enc (資訊加密),用於加密訊息流,該名稱後通常會帶有兩個數字,分別表示金鑰的長度和初始向量的長度,比如DES 56/56, RC2 56/128, RC4 128/128, AES 128/128, AES 256/256
  3. 資訊摘要 Mac(完整性校驗),用於建立報文摘要,確保訊息的完整性(沒有被篡改),演算法包括MD5,SHA等。
  4. PRF(偽隨機數函式),用於生成“master secret”。

完全搞懂上面的內容似乎還需要一本書的介紹,不過大致瞭解一下,有助於理解Cipher的名字,比如前面伺服器發回給客戶端的Cipher,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,從其名字可知,它是:
1. 基於TLS協議的;
2. 使用ECDHE、RSA作為金鑰交換演算法;
3. 加密演算法是AES-GCM(金鑰和初始向量的長度都是128),金鑰長度只是選擇了128,而不是256,背後的擔憂主要來自於效能——加密與解密是CPU密集型操作,過強的Cipher會帶來效能問題。
4. MAC演算法(這裡就是雜湊演算法)是SHA256。

熟悉了Cipher名字背後的含義後,讓我們看看像IIS這樣的Web伺服器如何選擇一個金鑰演算法呢?假如瀏覽器發來的金鑰演算法套件為[C1, C2, C3],而Windows Server支援的套件為[C4, C2, C1, C3]時,C1和C2都是同時被雙方支援的演算法,IIS是優先返回C1,還是C2呢?答案是C2。IIS會遍歷伺服器的金鑰演算法套件,取出第一個C4,發現瀏覽器並不支援;接下來取第二個C2,這個被瀏覽器支援!於是,IIS選擇了C2演算法,並將它包含在一個“ServerHello”握手協議中,發回給客戶端。

3. Client Key Exchange

這一步是第一次認證,即客戶端認證服務端證書,但是不幸的是,很多開發者為了簡單方便,在android程式碼中,將相關的邏輯進行了空實現,導致無論服務端的證書是什麼(可能服務端被攔截或代理),客戶端都選擇相信,這將為以後的安全通訊埋下巨大的隱患。

不論什麼平臺,裝置的作業系統中都會內建100多個全球公認的CA證書,說具體點就是裝置中儲存了這些知名CA的公鑰。當客戶端接收到伺服器的數字證書的時候,會進行如下驗證:
1. 證書鏈的可信性 trusted certificate path,客戶端會用裝置中內建的CA的公鑰嘗試解密證書中的數字簽名,如果所有內建的CA的公鑰都無法解密該數字簽名,說明該數字證書不是由一個全球知名的CA簽發的,這樣客戶端就無法信任該伺服器的數字證書。
2. 如果有一個CA的公鑰能夠成功解密該數字簽名,說明該數字證書就是由該CA的私鑰簽發的,因為被CA私鑰加密的密文只能被與其成對的CA公鑰解密。(這裡就能證明服務端是可信的,並沒有被代理,即資料的安全性)
3. 計算數字證書的hash摘要,並與解密後得到的證書hash摘要對比,如果一致表示該證書並沒有被篡改,否者,證書被中間人有過修改。(這裡就保證了內容的完整性)
4. 域名 domain,核查證書域名是否與當前的訪問域名匹配;
5. 有效期 expiry date,證書是否在有效時間範圍;
6. 證書是否吊銷 revocation,有兩類方式離線 CRL 與線上 OCSP,不同的客戶端行為會不同;

如果驗證不過,就會向訪問者顯示一個警告,由其選擇是否還要繼續通訊。
如果驗證通過,客戶端就會從證書中取出伺服器的公鑰。向伺服器傳送下面資訊。

  1. 在此之前的所有TLS握手資訊都是明文傳送的。但是本次在收到服務端的證書等資訊之後,客戶端會使用之前協商好的加密套件的演算法,產生一個48個位元組的隨機數Key,這個Key叫Pre-master, 然後用從證書中取出來的伺服器的公鑰和之前協商好的加密演算法加密這個Pre-master,結合之前的兩個隨機數生成session secret,注意這個加密是非對稱加密,除了服務端用自己的私鑰能解開,誰都解不開。
  2. 傳送一個編碼改變通知change_cipher_specchange_cipher_spec是一個獨立的協議,體現在資料包中就是一個位元組的資料,用於告知服務端,客戶端已經切換到之前協商好的加密套件的狀態,準備使用之前協商好的加密套件加密資料並傳輸了。
  3. change_cipher_spec傳輸完畢之後,客戶端傳送握手結束通知,encrypted_handshake_message,他是結合之前所有通訊引數的 hash 值與其它相關資訊生成一段資料,採用協商金鑰session secret進行加密,然後傳送給伺服器用於資料與握手驗證;
  4. 如果服務端需要對客戶端進行驗證,也就是在Server Hello中返回了Cerficate Request訊息,那麼此時,客戶端還需要額外向服務端傳送客戶端的證書,讓服務端來驗證客戶端的合法性(雙向認證)。我們本例中沒有這個要求,所以並沒有傳送客戶端證書。

4. Server Finish

服務端在接收到客戶端傳過來的Pre-master加密資料之後
1. 使用私鑰對這段加密資料進行解密,並對資料進行驗證,同時也會使用跟客戶端同樣的方式結合兩個隨機數生成session secret,一切準備好之後,會給客戶端傳送一個change_cipher_spec,告知客戶端已經切換到協商過的加密套件狀態,準備使用加密套件和session secret加密資料了。
2. 服務端也會使用session secret加密後一段Finish訊息傳送encrypted_handshake_message給客戶端,以驗證之前通過握手建立起來的加解密通道是否成功。
3. 如果服務端需要驗證客戶端身份,那麼首先驗證客戶端證書,驗證方法與步驟3基本一致。
4. 如果驗證失敗,服務端會發送alter message給客戶端, 用於指明在握手或通訊過程中的狀態改變或錯誤資訊,一般告警資訊觸發條件是連線關閉,收到不合法的資訊,資訊解密失敗,使用者取消操作等,收到告警資訊之後,通訊會被斷開或者由接收方決定是否斷開連線。

最後結果如下圖:

5. 驗證結果,傳送資料

客戶端最後會收到伺服器傳送的encrypted_handshake_message,用來驗證伺服器傳送的資料和金鑰,如果驗證通過則握手完成,到此就說明客戶端和服務端的兩次握手通訊都能對Finish資訊進行正常加解密且訊息正確的被驗證,雙方握手通道已經安全建立成功,接下來,就可以使用上面產生的session secret對資料進行加密傳輸了,如下所示:

到此我們就對整個SSL/TLS的握手流程進行了一次詳細的講解。相信在經過自己的學習和文章的閱讀後,這些都不是問題。

不同的加密演算法握手的過程略有不同,

基於RSA演算法的握手精簡如下:

基於用Diffie–Hellman演算法交換premaster secret 的流程

八、常用證書格式

我們再使用證書的時候,會遇見很多副檔名的證書,那麼每種副檔名是什麼意思,能不能相互替代使用,解釋如下:

X.509 是一個標準,也是一個數字文件,這個文件根據RFC 5280來編碼並簽發,一份X.509證書是一些標準欄位的集合,這些欄位包含有關使用者或裝置及其相應公鑰的資訊。

編碼 (也用於副檔名)
- .DER - 副檔名DER用於二進位制DER編碼的證書,不可讀。這些證書也可以用CER或者CRT作為副檔名。 Java和Windows伺服器偏向於使用這種編碼格式,比較合適的說法是“我有一個DER編碼的證書”,而不是“我有一個DER證書”。
- .PEM - 副檔名PEM用於ASCII(Base64)編碼的各種X.509 v3 證書。以“—–BEGIN…”開頭, “—–END…”結尾,內容是BASE64編碼,Apache和Linux伺服器偏向於使用這種編碼格式。

常用的副檔名
- .KEY - 通常用來存放一個公鑰或者私鑰,並非X.509證書,編碼可能是PEM,也可能是DER.
- .CSR - 是Certificate Signing Request的縮寫,即證書籤名請求,這不是證書,是生成證書時要把這個提交給權威的證書頒發機構。其核心內容是一個公鑰(當然還附帶了一些別的資訊),在生成這個申請的時候,同時也會生成一個私鑰,私鑰要自己保管好.當權威證書頒發機構頒發的證書過期的時候,你還可以用同樣的csr來申請新的證書,key保持不變.
- .CRT - certificate的縮寫,其實還是證書的意思,常見於Linux系統,有可能是PEM或者DER編碼,大多數應該是PEM編碼.
- .CER - certificate的縮寫,其實還是證書的意思,常見於Windows系統,有可能是PEM或者DER編碼,大多數應該是DER編碼.

注意:CRT檔案和CER檔案只有在使用相同編碼的時候才可以安全地相互替代。

  • .PFX/PKCS12 - predecessor of PKCS#12,包含了證書和私鑰,對Linux伺服器來說,一般來說CRT和KEY是分開存放在不同檔案中的,但Windows的IIS則將它們存在一個PFX檔案中,並通過提取密碼來保護。
  • .JKS/JCEKS - Java金鑰庫(KeyStore)的兩種比較常見型別,包含了證書和私鑰,利用Java的“keytool”的工具,可以將PFX轉為JKS,當然了,keytool也能直接生成JKS,JCEKS在安全級別上要比JKS強,使用的Provider是JCEKS(推薦),使用使用TripleDES 保護KeyStore中的私鑰;
  • .BKS – Bouncy Castle Provider,包含了證書和私鑰, android系統支援的型別,它使用的也是TripleDES來保護金鑰庫中的私鑰,它能夠防止證書庫被不小心修改(Keystore的keyentry改掉1個bit都會產生錯誤),BKS能夠跟JKS互操作。

注意:通過工具 BKS、JKS、PFX 三種格式的證書均可以相互轉換

OpenSSL簡單地說,OpenSSL是SSL的一個實現,SSL只是一種規範.理論上來說,SSL這種規範是安全的,目前的技術水平很難破解,但SSL的實現就可能有些漏洞,如著名的“心臟出血”。OpenSSL還提供了一大堆強大的工具軟體,強大到90%我們都用不到.

證書編碼的轉換
PEM轉為DER openssl x509 -in cert.crt -outform der -out cert.der
DER轉為PEM openssl x509 -in cert.crt -inform der -outform pem -out cert.pem
(提示:要轉換KEY檔案也類似,只不過把x509換成rsa,要轉CSR的話,把x509換成req…)

九、部署自簽名SSL證書為什麼不安全

證書的來源有三種,一種是CA認證的機構頒發,這種當然最安全,第二種是像12306這樣的使用其他機構頒發的未被CA認可的證書,第三種是我們開發者自己給自己頒發證書。那麼他們都具有以下特點:

  1. 自簽證書最容易被假冒和偽造,而被欺詐網站所利用
  2. 自簽證書最容易受到SSL中間人攻擊
  3. 以上這兩點都是由於自簽證書不受瀏覽器信任,而網站告訴使用者要信任而造成!所以,作為使用者,千萬不要繼續瀏覽瀏覽器有型別如下警告的網站
  4. 自簽證書支援不安全的SSL通訊重新協商機制
  5. 自簽證書支援非常不安全的SSL V2.0協議
  6. 自簽證書沒有可訪問的吊銷列表
  7. 自簽證書使用不安全的1024位非對稱金鑰對,微軟已經要求所有受信任的根證書頒發機構必須於2010年12月31日之前升級其不安全的1024位根證書到2048位和停止頒發不安全的1024位使用者證書,12 月 31 日之後會把不安全都所有 1024 位根證書從 Windows 受信任的根證書頒發機構列表中刪除!
  8. 自簽證書證書有效期太長,短則5年,長則20年、30年的都有,並且還都是使用不安全1024位加密演算法。

SRCA,12306證書,中鐵數字證書認證中心(Sinorail Certification Authority,簡稱“SRCA”)成立於2003年,主要提供電子認證服務、電子認證產品及一體化的電子認證解決方案,官網點選這裡中鐵數字證書認證中心

以下是12306證書的完整內容,我們發現與上面的每一項都很完美的吻合了!!!


為何所有Windows受信任的根證書有效期都是20年或30年?

因為:
一是根證書金鑰生成後是離線鎖保險櫃的,並不像使用者證書一樣一直掛在網上;
二是根證書採用更高的金鑰長度和更安全的專用硬體加密模組。

Charles為什麼能抓到Https的資料包?為什麼測試的時候會出現微辦公的證書是不可信任的?

因為Charles作為中間人,代理了客戶端與服務端的通訊,並且在客戶端安裝了中間人的證書,使得中間人的證書變成了可信證書。

程式碼分析

證書鎖定儘管帶了較高的安全性,但是這種安全性的提高卻犧牲了靈活性。一旦當證書發生變化時,我們的客戶端也必須隨之升級,除此之外,我們的服務端不得不為了相容以前的客戶端而做出一些妥協或者說直接停用以前的客戶端,這對開發者和使用者來說並不是那麼的友好。但實際上,極少情況下我們才會變動證書。因此,如果產品安全性要求比較高還是啟動證書鎖定吧。

看起來好像解決了我們的問題,實則帶來更大的危害。此時,雖然能建立HTTPS連線,但是無形之中間人攻擊打開了一道門。此時,黑客完全可以攔截到我們的HTTPS請求,然後用偽造的證書冒充真正服務端的數字證書,由於客戶端不對證書做驗證(也就沒法判斷服務端到底是正常的還是偽造的),這樣客戶端就會和黑客的伺服器建立連線。這就相當於你以為你對的對面是個美女,卻沒有想到已經被掉包了,想想“狸貓換太子”就明白了。

十、HTTPS效能損耗

前文討論了HTTPS原理與優勢:身份驗證、資訊加密與完整性校驗等,且未對TCP和HTTP協議做任何修改。但通過增加新協議以實現更安全的通訊必然需要付出代價,HTTPS協議的效能損耗主要體現如下:

  1. 增加延時

    分析前面的握手過程,一次完整的握手至少需要兩端依次來回兩次通訊,至少增加延時2*RTT(Round-Trip Time,往返時間),利用會話快取從而複用連線,延時也至少1* RTT。

  2. 消耗較多的CPU資源

    除資料傳輸之外,HTTPS通訊主要包括對對稱加解密、非對稱加解密(伺服器主要採用私鑰解密資料);壓測 TS8 機型的單核 CPU:對稱加密演算法AES-CBC-256 吞吐量 600Mbps,非對稱 RSA 私鑰解密200次/s。不考慮其它軟體層面的開銷,10G 網絡卡為對稱加密需要消耗 CPU 約17核,24核CPU最多接入 HTTPS 連線 4800;


    靜態節點當前10G 網絡卡的 TS8 機型的 HTTP 單機接入能力約為10w/s,如果將所有的HTTP連線變為HTTPS連線,則明顯RSA的解密最先成為瓶頸。因此,RSA的解密能力是當前困擾HTTPS接入的主要難題。

實際上對於https:

  1. 證書費用以及更新維護。大家覺得申請證書很麻煩,證書也很貴,可是證書其實一點都不貴,便宜的一年幾十塊錢,最多也就幾百。而且現在也有了免費的證書機構,比如著名的 mozilla 發起的免費證書專案:let’s encrypt(https://letsencrypt.org/)就支援免費證書安裝和自動更新。
  2. HTTPS 降低使用者訪問速度。HTTPS 對速度會有一定程度的降低,但是隻要經過合理優化和部署,HTTPS 對速度的影響完全可以接受。在很多場景下,HTTPS 速度完全不遜於 HTTP,如果使用 SPDY,HTTPS 的速度甚至還要比 HTTP 快。大家現在使用百度 HTTPS 安全搜尋,有感覺到慢嗎?

十一、HTTPS接入優化

  1. CDN接入

    HTTPS 增加的延時主要是傳輸延時 RTT,RTT 的特點是節點越近延時越小,CDN 天然離使用者最近,因此選擇使用 CDN 作為 HTTPS 接入的入口,將能夠極大減少接入延時。CDN 節點通過和業務伺服器維持長連線、會話複用和鏈路質量優化等可控方法,極大減少 HTTPS 帶來的延時。

  2. 會話快取

    雖然前文提到 HTTPS 即使採用會話快取也要至少1*RTT的延時,但是至少延時已經減少為原來的一半,明顯的延時優化;同時,基於會話快取建立的 HTTPS 連線不需要伺服器使用RSA私鑰解密獲取 Pre-master 資訊,可以省去CPU 的消耗。如果業務訪問連線集中,快取命中率高,則HTTPS的接入能力講明顯提升。當前TRP平臺的快取命中率高峰時期大於30%,10k/s的接入資源實際可以承載13k/的接入,收效非常可觀。

  3. 硬體加速

    為接入伺服器安裝專用的SSL硬體加速卡,作用類似 GPU,釋放 CPU,能夠具有更高的 HTTPS 接入能力且不影響業務程式的。測試某硬體加速卡單卡可以提供35k的解密能力,相當於175核 CPU,至少相當於7臺24核的伺服器,考慮到接入伺服器其它程式的開銷,一張硬體卡可以實現接近10臺伺服器的接入能力。

  4. 遠端解密

    本地接入消耗過多的 CPU 資源,浪費了網絡卡和硬碟等資源,考慮將最消耗 CPU 資源的RSA解密計算任務轉移到其它伺服器,如此則可以充分發揮伺服器的接入能力,充分利用頻寬與網絡卡資源。遠端解密伺服器可以選擇 CPU 負載較低的機器充當,實現機器資源複用,也可以是專門優化的高計算效能的伺服器。當前也是 CDN 用於大規模HTTPS接入的解決方案之一。

  5. SPDY/HTTP2

    前面的方法分別從減少傳輸延時和單機負載的方法提高 HTTPS 接入效能,但是方法都基於不改變 HTTP 協議的基礎上提出的優化方法,SPDY/HTTP2 利用 TLS/SSL 帶來的優勢,通過修改協議的方法來提升 HTTPS 的效能,提高下載速度等。

  6. 如果需要進一步減小證書大小,可以選擇 ECC(Elliptic Curve Cryptography,橢圓曲線密碼學)證書。

    256 位的 ECC Key 等同於 3072 位的 RSA Key,在確保安全性的同時,體積大幅減小。ECC 證書這麼好,為什麼沒有普及呢?最主要的原因是它的支援情況並不好。例如 Windows XP 不支援,導致使用 ECC 證書的網站在 Windows XP 上只有 Firefox 能訪問(Firefox 證書那一套完全自己實現,不依賴作業系統)。另外,Android 平臺也只有 Android 4+ 才支援 ECC 證書。所以,確定使用 ECC 證書前需要明確使用者系統分佈情況。

感謝以下作者:

如果你覺得好,對你有過幫助,請給我一點打賞鼓勵吧,一分也是愛呀!