HTTPS祥解

本文來源:騰訊優圖實驗室 https://mp.weixin.qq.com/s/ibwNtDc2zd2tdhMN7iROJw

筆者來自騰訊優圖實驗室,優圖實驗室專注於圖像處理、模式識別、深度學習,在人臉識別、圖像識別、醫療AI、交通、OCR 等領域積累了領先的技術水平和完整的解決方案。近年來,優圖在計算機視覺領域的研究和應用積累了深厚的底蘊和豐富的行業落地經驗。筆者所在的團隊主要負責視覺AI能力賦能邊緣計算設備的研發工作。一直以來,在實驗室甚至整個公司特別強調“安全和隱私”,近半年,筆者在用 GoLang 開發智能邊緣計算設備的網絡通信項目時,常被要求務必重視“通信的安全和隱私”。期間,對接了多個合作方,有的要求“公網下要防止域名劫持”,有的要求“客戶端上報要帶‘證書’啊,更安全”,還有要求除了要用 HTTPS,還要在業務邏輯上再進行二次哈希、摘要、加密等等。由於筆者對 HTTPS 的認知也僅停留在 “HTTPS 比 HTTP 更安全”的層面上,在項目開發中遇到很多通信相關的問題經常束手無策,因此沉下心來,認認真真學習了 HTTPS 並記錄成此文。

I. HTTPS 之靈魂三問

要說 HTTPS,搞 IT 的甚至是不搞 IT 的,都知道:“HTTPS 比 HTTP 安全”。因此但凡要開發涉及網絡傳輸的項目時,得到的需求一定有:“要用 HTTPS”。

 

1.1 HTTPS 是什麼?

維基百科對 HTTPS 的解釋是:

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

抓重點:HTTPS=HTTP over SSL/TLS,也就是說,HTTPS 在傳輸層 TCP 和應用層 HTTP 之間,多走了一層 SSL/TLS。

由此可見,TLS/SSL 是 HTTPS 的核心! 那麼,這個TLS/SSL又是何方神聖呢?文章How to use SSL/TLS to Secure Your Communications: The Basics指出:

The SSL/TLS protocol functions between two layers of the OSI Presentation layer.The handshake and record layers operate over TCP/IP to encrypt data received directly from the Application layer.

SSL/TLS 協議作用在傳輸層和應用層之間,對應用層數據進行加密傳輸。

借用文中的圖,可以直觀感受到:SSL和TLS都是加密協議SSL,全稱 Secure Socket Layer,在 1994 年由網景公司(Netscape)最早提出 1.0 版本;TLS,全稱 Transport Layer Security,則是 1999 年基於 SSL3.0 版本上改進而來的。官方建議棄用 SSL 而保留和採用 TLS,但是由於歷史原因,SSL 仍然存在,而且很多人已經習慣 SSL 這個名詞,因此現在索性就叫成 SSL/TLS。

SSL/TLS 的發展史,可以閱讀文章《SSL/TLS 發展歷史和 SSLv3.0 協議詳解》;關於兩者的異同,推薦閱讀文章《SSL vs. TLS - What’s the Difference?》。

 

1.2 HTTPS 爲什麼?

肯定有不少同學不假思索:“當然是 HTTP 不安全,HTTPS 安全,所以選擇 HTTPS 唄!”那麼,HTTPS 比 HTTP“好”在哪裏?

維基百科上對 HTTP 的解釋如下:

設計 HTTP 最初的目的是爲了提供一種發佈和接收 HTML 頁面的方法。

HTTP 的發展是由蒂姆·伯納斯-李於 1989 年在歐洲核子研究組織(CERN)所發起。HTTP 的標準制定由萬維網協會(World Wide Web Consortium,W3C)和互聯網工程任務組(Internet Engineering Task Force,IETF)進行協調,最終發佈了一系列的 RFC,其中最著名的是 1999 年 6 月公佈的 RFC 2616,定義了 HTTP 協議中現今廣泛使用的一個版本——HTTP 1.1。

HTTP 協議是爲了傳輸網頁超文本(文本、圖像、多媒體資源),以及規範客戶端和服務器端之間互相請求資源的方法的應用層協議。在 1989 年最早推出了 HTTP 0.9 版本,而 1999 年公佈的 HTTP 1.1 是到目前(2020 年)仍舊廣泛使用的版本(引自《HTTP 協議幾個版本的比較》)。

但是這個 HTTP 1.1 版本存在一個很大的問題-明文傳輸(Plaintext/Clear Text),這個問題在互聯網時代的今天是致命的,一旦數據在公共網絡中被第三方截獲,其通信內容輕而易舉地就被竊取了。

因此,HTTPS 應運而生,它被公認的三大優勢有:

  1. 數據加密,防竊聽

  2. 身份驗證,防冒充

  3. 完整性校驗,防篡改

囉嗦說一句:第 1 點確實是解決了 HTTP 明文傳輸;至於第 2 和第 3 點,其他一些應用層協議也會遇到(服務端被冒充、數據被篡改是網絡傳輸中“較常見”的問題)。

再插一句題外話:2015 年推出的 HTTP 2 在 HTTP 1.1 的基礎上有很大改進,其中一點就是 HTTPS。對 HTTP 2 有興趣的同學推薦閱讀《HTTP/2 中的常見問題》、《OPINION HTTP versus HTTPS versus HTTP/2》。

 

1.3 HTTPS 怎麼做?

本文接下來將從 HTTPS 的 3 個優勢展開說明,即:

  1. 數據加密,即 HTTPS 是怎麼進行數據加密的。本章介紹 HTTPS 中的對稱加密和非對稱加密

  2. 身份驗證,即 HTTPS 是怎麼讓客戶端相信“發給我數據的服務端是我想要的服務器”。本章介紹 HTTPS 的 CA 和證書

  3. 完整性校驗,即 HTTPS 是怎麼做數據完整性校驗以防止被篡改。本章介紹 HTTPS 的哈希

最後,爲了整篇文章的完整性,還會增加以下幾個內容:

  1. HTTPS 流程,即客戶端和服務器端 HTTPS 通信全過程

  2. 實際問題,記錄了筆者在實戰中遇到 HTTPS 相關問題

     


 

 

II. 數據加密:HTTPS 的對稱加密和非對稱加密

相信不少同學會說"對稱加密和非對稱加密有什麼好講的?前者只有一把密鑰做加解密;後者有兩把密鑰,公鑰和私鑰,互爲加解密,公鑰給對方,私鑰自己用。HTTPS 兩者都有。好了,這章可以結束啦。"

三個問題:

  1. HTTPS 爲什麼同時要有對稱加密和非堆成加密兩種加密方式?

  2. HTTPS 對稱加密的密鑰(本文稱爲 SK,下同)如何產生和傳輸?

  3. HTTPS 的有幾套非對稱加密?目的是什麼?是否可以省略?

好,一個問題一個問題來。

問題 1:HTTPS 爲什麼同時要有對稱加密和非對稱加密兩種加密方式?

默認各位同學已經知曉對稱加密和非對稱加密(瞭解基本原理即可),不清楚的同學推薦閱讀知乎文章-《對稱加密與非對稱加密》,文章最後指出了這兩個加密方式的優缺點,原文如下:

(1)對稱加密加密與解密使用的是同樣的密鑰,所以速度快,但由於需要將密鑰在網絡傳輸,所以安全性不高。

(2) 非對稱加密使用了一對密鑰,公鑰與私鑰,所以安全性高,但加密與解密速度慢。

那麼解決辦法有嗎?有,文章隨後說道:

(3)解決的辦法是將對稱加密的密鑰使用非對稱加密的公鑰進行加密,然後發送出去,接收方使用私鑰進行解密得到對稱加密的密鑰,然後雙方可以使用對稱加密來進行溝通。

確實,HTTPS(最開始)就是這麼做的!其思路大致如下:

1). 首先一定要明確HTTPS既有對稱加密,又有非對稱加密。-\> 2).由於對稱加密性能高速度快,因此在傳輸數據時(也就是對話內容)採用對稱加密。-\>3).但是對稱加密的密鑰SK,既沒辦法預先設置(密鑰不可能只有一把,服務器端維護大量密鑰也不具備可行性),因此只能選擇在對話前通過網絡協商出一把新的SK。-\>4). 爲了確保SK的傳輸安全,使用非對稱加密來協商SK。

HTTPS 的這種設計同時兼顧了安全和效率,讚歎先驅們的智慧!

 

問題 2:HTTPS 對稱加密的密鑰 SK 如何產生和傳輸?

通過第一個問題,我們知道了 HTTPS 分爲2 個過程

  1. 協商對稱加密密鑰 SK 的非對稱加密階段,稱爲TLS 握手階段

  2. 使用 SK 對數據(對話內容)進行對稱加密的階段,稱爲數據通信階段

過程 2數據通信階段:發送端首先用密鑰 SK 對通信內容進行對稱加密,接着通過網絡傳輸出去;對端收到數據後,用 SK 先將數據解密,於是就得到了通信內容。這裏筆者有一個問題尚未求證:在數據傳輸過程中,是否會對通信數據進行哈希以確保其不被篡改?姑且記一筆。

過程 1TLS 握手階段:協商密鑰 SK。網上關於這個知識點的文章有很多,然而一些已經過時,一些則不全。就協商密鑰 SK 這塊,筆者推薦《掃盲 HTTPS 和 SSL/TLS 協議[3]:密鑰交換(密鑰協商)算法及其原理》和《密鑰協商機制》。本文直接扔出結論,HTTPS 協商對稱加密密鑰 SK 的辦法有很多種,介紹 3 種較爲常見的辦法:

  1. 基於非對稱加密算法

  2. 基於專用密鑰交換算法,常見有 DH、ECDH 等

  3. 基於共享的 secret,常見有 PSK,SRP 等

方法 1. 基於非對稱加密算法

維基百科對於非對稱加密算法的解釋:公開密鑰密碼學(英語:Public-key cryptography)也稱非對稱式密碼學(英語:Asymmetric cryptography)是密碼學的一種算法,它需要兩個密鑰,一個是公開密鑰,另一個是私有密鑰;一個用作加密,另一個則用作解密。使用其中一個密鑰把明文加密後所得的密文,只能用相對應的另一個密鑰才能解密得到原本的明文;甚至連最初用來加密的密鑰也不能用作解密。由於加密和解密需要兩個不同的密鑰,故被稱爲非對稱加密;不同於加密和解密都使用同一個密鑰的對稱加密。雖然兩個密鑰在數學上相關,但如果知道了其中一個,並不能憑此計算出另外一個;因此其中一個可以公開,稱爲公鑰,任意向外發布;不公開的密鑰爲私鑰,必須由用戶自行嚴格祕密保管,絕不透過任何途徑向任何人提供,也不會透露給被信任的要通信的另一方。

非對稱加密 RSA 協商密鑰的辦法,是 HTTPS(嚴格說是 SSL/TLS 協議)最早的辦法,其過程如下:

  1. 客戶端給服務端發送請求;

  2. 服務端返回客戶端自己的公鑰 PuK;

  3. 客戶端產生本次對話的對稱密鑰 SK,並用 PuK 進行加密得到 SK_Enc 後傳給服務端;

  4. 服務端收到 SK_Enc 後用自己的私鑰 PrK 解密得到 SK;若成功,則返回客戶端 OK,否則終止對話.

  5. 接下來,客戶端和服務端的對話均用 SK 加密後傳輸。

方法 2:基於專用密鑰交換算法

方法 1 是被大部分人熟知的,但是存在一個問題:如果服務端的私鑰 PrK 泄露了,那麼 HTTPS 所做的加密也就不安全了。

因此,就有了密鑰交換算法(有說法是 keyless 方法)。方法原理筆者沒有深究(數學功底有限,看到大量的公式證明還是會煩…),DH 和 ECDH 協商密鑰算法大致過程如下:

ECDH 算法中的 A 和 B,在有的材料中也被稱爲PreMaster-Secret。最終協商得到的密鑰 SK 也被稱爲Master Secret,也被稱爲Session Key

直接給出結論:ECDH 比 DH 算法更快,有說法是 10 倍;而且 ECDH 比 DH 更難破解,可行性更好。推薦閱讀《Elliptic Curve Cryptography: ECDH and ECDSA》、《完全吃透 TLS/SSL》更進一步瞭解 DH 和 ECDH 算法。

方法 3:基於共享的 secret

這類做法就是在客戶端和服務端預設好對稱加密密鑰,握手階段只需要傳遞類似鑰匙 id 即可。代表算法有 PSK。

 

問題 3:HTTPS 的有幾套非對稱加密?目的是什麼?是否可以省略?

直接給出答案:2 套非對稱加密

第一套用於協商對稱加密密鑰 SK(問題 2 一直在討論的內容);第二套用於數字證書籤名加密(接下來一章會詳細討論 CA 證書)。這兩者的區別是:前者是服務器端(如果是雙向驗證的話,客戶端也會有一套非對稱加密公私鑰)產生的。私鑰在服務端上;後者是 CA 機構產生的,私鑰在 CA 機構那邊。

並且,這 2 套都不可以省略。(這個說法略不嚴謹,但是在實際操作中,確實都不建議省略。)

 


 

 

III. 身份驗證:HTTPS 的證書

筆者認爲,對大部分程序員來說,工作中遇到的 HTTPS 相關問題,80%~90%都是跟證書相關的。因此,瞭解證書非常關鍵!

3.1 證書是什麼?

解釋這個問題之前,先看幾個關鍵詞:CACA 機構數字證書數字簽名(證書)指紋(CA)證書HTTPS 證書SSL/TLS 證書

理一理上面這些關鍵詞之間的關係:

  • CA,CA 機構:機構/組織概念。

  • 數字證書,(CA)證書,HTTPS 證書,SSL/TLS 證書:CA 簽發的數字證書。

  • 數字簽名,(證書)指紋:CA 簽發的證書的內容之一,一段加密的密文。

智庫百科對數字證書的解釋是:

數字證書也稱公開密鑰證書,是指用於電子信息活動中電子文件行爲主體的驗證和證明,並可實現電子文件保密性和完整性的電子數據。數字證書是一個經證書認證中心(Certification Authority,簡稱 CA)發行的文件。

數字證書包含有行爲主體信息和證書認證機構的數字簽名。數字簽名是指以電子形式存在,可依附在電子文件中用於辨識電子文件的簽署者及表示對該電子文件內容負責所使用的電子數字標識。

抓重點:數字證書用於主體身份驗證。

首先,數字證書=主體信息+數字簽名

Windows 下,我們可以在 Chrome 瀏覽器上點擊地址欄的“鎖”標記後會出現下拉框,接着點擊“證書”即可看到通過 HTTPS 訪問該服務器時的數字證書。具體操作如下:

  • 證書“常規”頁面,是關於該證書的一個籠統介紹,包括簽發該證書的 CA 機構、該證書綁定的域名(頒發給)、證書有效期。

  • 證書“詳細信息”頁面,以鍵值對形式展示了這張證書的完整內容。(後文將詳細介紹證書內容)

  • 證書的“證書路徑”,以層級結構展示了從該證書綁定的域名一直到根證書的路徑,這就是證書鏈。(後文會展開介紹證書鏈)

看完了 Chrome 瀏覽器上的證書,在讓我們通過 Wireshark 抓包來來看看數字證書:

對比 Chrome 上看到的數字證書和 Wireshark 抓包得到的數字證書,可以看到兩者呈現的證書內容是一致的。總結來看,一張完整的數字證書包括:

  • 主體的必要信息:版本(version)、序列號(serialNumber)、簽名算法(signatureAlgorithm)、頒發者(issuer)、有效期(validity)、使用者(subject)、公鑰信息(subjectPublicKeyInfo)

  • 主體的擴展信息(extension):如密鑰標識符、證書策略等

  • 數字簽名(signature),也稱指紋

抽象爲下圖:

 

3.2 爲什麼是數字證書呢?

HTTPS 已經對通信數據進行了加密,爲什麼還要驗證身份?說好的“人與人之間最基本的信任呢?”

這還不是因爲各路黑客、駭客們總是在製造各種攻擊嗎?(捂臉)其中一個大名鼎鼎的中間人攻擊(Man-In-The-Middle Attack,MITM 攻擊),簡單的講,“中間人”在客戶端和服務端都不知情的情況下,夾在雙方之間竊聽甚至篡改通信信息,過程見下圖(圖引自《HTTPS 中間人攻擊實踐(原理·實踐)》):

在 HTTPS 的握手階段,一端向對端發送請求,對端返回自己的公鑰;而一端未驗證對方的身份和公鑰,直接協商密鑰。“中間人”看到了這個漏洞,夾在中間截獲了對端的公鑰,替換成了自己的公鑰。正是這步“拿錯了公鑰”或者說“信錯了對端”,使得 HTTPS 爲加密(密鑰協商的非對稱加密和通信數據的對稱加密)所做的努力全部泡湯。

可見,在 HTTPS 中,“確保對端身份正確”即“確保拿到的公鑰正確”,而在網絡通信中所謂的“身份”,一般指的是通信一端的域名IP 地址甚至是Mac 地址。所以,數字證書同時包含了通信一端的身份信息公鑰信息

但是數字證書會在網絡中傳輸(由被要求驗證身份的一端通過網絡傳給另一端),這就意味着證書也可能會被竊取篡改。這個時候權威的 CA 機構就出馬了,他想了個辦法:加了一個“防僞標識”— 數字簽名。具體做法如下:

signature = RSA(PriKey_CA, Hash(message))

這裏囉嗦幾句:數字簽名生成過程是首先對原文作哈希,把一段不定長的文本映射成固定長度的字符空間,接着再用 CA 機構的私鑰對這段定長字符做加密。大大提高了整體的運算效率。

 

3.3 證書是怎麼工作的?

要了解證書是怎麼做“身份驗證”,即“防冒充”,得從 2 個角度來說明:

  • 申請證書,即需要被驗證身份的一端,需要申請一份能夠驗證自己身份的證書

  • 驗證證書,即需要驗證對方身份的一端,拿到證書後驗證對端的身份

請注意,這裏有一個前提:這張證書必須是由權威 CA 機構頒發的,且尚在有效期內;或者是一張信任的私人證書

申請證書

CA 機構和證書的分類本文不討論,推薦閱讀《細說 CA 和證書》,這裏我們討論正規權威 CA 機構簽發的證書,至於是 DV、OV 還是 EV,只是安全強度問題,工作原理是一樣的。

總結申請證書的過程:用戶向 CA 機構提交自己的信息(如域名)和公鑰(用戶自己生成的非對稱加密公鑰,用於 TLS 握手階段和另一端協商密鑰用),CA 機構生成數字證書,如下圖:

驗證證書

收到對端發過來的證書,執行證書申請的“逆過程”即可,總結如下圖:

接受證書的一端先對除數簽名的其他部分做一次相同的哈希算法(證書中指明瞭哈希算法),得到這段文本的哈希映射,記作 H1;獲取 CA 機構的公鑰對數字簽名屬性做解碼,得到了 CA 機構計算出的哈希映射,記作 H2。對比 H1 和 H2 兩個字符串是否嚴格相等,若是,代表該證書的信息未被篡改,證書有效;否則,證書內容被篡改,證書無效。

若證書有效,接受端會再進行對端的身份校驗(驗證域名),若身份驗證通過,接收端會拿證書上的公鑰(也是對端自己生產的非對稱加密公鑰)加密接下來整個 TLS 握手階段的信息之後,發送給對端。

這個過程中有一個問題:CA 機構的公鑰怎麼獲取?

回答:提前內置。

衆所周知,操作系統和瀏覽器在軟件安裝階段會在其特定目錄下放置一堆的證書。如 Windows 的根證書管理在 certmgr 下:

這些證書都有個特點:權威 CA 機構發佈的根證書(Root Certificate)。根證書有幾個特點:

  • 沒有上層機構再爲其本身作數字簽名

  • 證書上的公鑰即爲 CA 機構發佈的公鑰

  • 權威 CA 機構的自簽證書

而這些根證書會跟很多軟件,包括操作系統、瀏覽器一起被安裝到用戶設備上。即使沒有被提前安裝好,這些根證書也可以在 CA 機構的官網上獲取得到。

目前全球大型權威 CA 機構有 Symantec、GeoTrust、Comodo 以及 RapidSSL 等,並且這些機構頒發的 SSL 數字證書,在市場的佔有率是非常的高。(節選自《SSL 證書頒發機構有哪些》)

本地被內置了這麼多的根證書,那要怎麼知道我這份證書應該要用哪一個根證書來驗證呢?

回答:證書信任鏈。

在信任鏈上有 3 類證書:根證書中介證書用戶證書。根證書前文已有說明,用戶證書就是對端發過來的證書,或者說是用戶向權威 CA 機構綁定了自己身份(主要指域名)和自己公鑰的證書。中介證書可以理解由權威 CA 機構委派的代理機構簽發的數字證書,推薦閱讀《What is an intermediate certificate?》。中介證書或者說是中介機構的存在是爲了保證根證書的密鑰的安全性。

細心的同學仔細看一看 certmgr 會發現有一個分類是“中間證書頒發機構”,這裏存放的就是中介證書。用戶證書絕大多數是通過權威的 CA 機構的代理中介機構頒發。

這麼來說,根據對端發來的用戶證書尋找對應的根證書豈不是更困難了?

自問自答:這是一個在樹形數據結構中,從葉子節點搜索根節點的過程,直接一個最原始的深搜(DFS)不就可以了嘛?舉例說明,如下圖(引自Wikipedia-Chain of trust):

  1. 從用戶證書開始。

  2. 記“Issuer”字段的值爲 i1,搜索本地證書,尋找由“Subject”爲 i1 的證書。

  3. 若沒有找到,結束返回證書無效;否則,跳到步驟 4)。

  4. 判斷該證書的 Issuer 值是否等於 Subject 值。

  5. 若是,則該證書是根證書,結束返回該證書;否則跳到步驟 6)。

  6. 以該證書開始,跳轉 2)(繼續搜索)。

更多關於信任鏈的知識點,推薦閱讀《What is the SSL Certificate Chain?

 

3.4 證書怎麼樣?

相信不少同學或多或少接觸過證書文件,比如.pem、.crt、.cer、.key 等,於是問題就來了:

“爲什麼有這麼多不同後綴名的證書啊?他們有什麼聯繫和區別?”

回答這個問題要從 3 個層面來分析:

  • 證書標準

  • 證書編碼格式

  • 文件擴展名

證書標準

數字證書的格式普遍採用的是 X.509 國際標準,維基百科對於 X.509 解釋如下:

X.509 是密碼學裏公鑰證書的格式標準。X.509 證書已應用在包括 TLS/SSL 在內的衆多網絡協議裏,同時它也用在很多非在線應用場景裏,比如電子簽名服務。X.509 證書裏含有公鑰、身份信息(比如網絡主機名,組織的名稱或個體名稱等)和簽名信息(可以是證書籤發機構 CA 的簽名,也可以是自簽名)。對於一份經由可信的證書籤發機構簽名或者可以通過其它方式驗證的證書,證書的擁有者就可以用證書及相應的私鑰來創建安全的通信,對文檔進行數字簽名。

 

X.509 是 ITU-T 標準化部門基於他們之前的 ASN.1 定義的一套證書標準。

證書的編碼格式

X.509 標準的證書文件具有不同的編碼格式:PEM 和 DER。

  1. PEM

    PEM,全稱 Privacy Enhanced Mail,以文本格式存儲,以 -----BEGIN
    XXX-----開頭、-----END XXX-----結尾,中間內容是 BASE64 編碼數據。其文本內容大概如下:

    html -----BEGIN CERTIFICATE----- Base64編碼過的證書數據 -----END CERTIFICATE-----

通常,PEM 格式可以存儲公鑰、私鑰、證書籤名請求等數據。查看 PEM 格式證書的信息一般採用如下命令:

openssl x509 -in xxx.pem -text -noout

Apache 和 Nginx 服務器偏向於使用這種編碼格式.

  1. DER

    DER,全稱 Distinguished Encoding Rules,以二進制存儲,因此文件結構無法直接預覽,只能通過如下命令查看:

    html openssl x509 -in xxx.der -inform der -text -noout

    DER 格式也可以存儲公鑰、私鑰、證書籤名請求等數據。Java 和 Windows 應用偏向於使用這種編碼格式。

當然同一 X.509 證書的不同編碼之間可以互相轉換:

  • PEM 轉爲 DER:

    openssl x509 -in xxx.pem -outform der -out xxx.der
    
  • DER 轉爲 PEM:

    openssl x509 -in xxx.der -inform der -outform pem -out xxx.pem
    

文件擴展名

不同的擴展名可以分爲以下幾類:

  • 證書:存放數字證書,X.509 標準,格式可能是 PEM 或 DER。.crt、.cer

  • 密鑰:用來存放一個 RSA 公鑰或私鑰,這類文件不是 X.509 標準,但是是 PEM 或 DER 格式。後綴名有.key。

  • 證書+密鑰:可同時存放證書和 RSA 公鑰/.pem、.der、.p12

  • 證書請求:並不是證書,而是證書籤名請求。csr

 



 

IV. 完整性校驗:HTTPS 的哈希

哈希,鍵值對數據結構,通過哈希函數把一個空間映射到另一個空間。非常好用的一個工具,而且哪哪兒都有它的影子,比如負載均衡的一致性哈希、密碼學中用於信息加密或數據校驗的各種哈希(SHA、MD5 等)、二維空間定位的 GeoHash、對象相似度的 SimHash 等等。

HTTPS 的的哈希一共用在 2 個地方:

4.1 證書的數字簽名

具體做法在上文證書一章節已經說過,不再贅述。在這裏使用哈希的目的主要是爲了減少非對稱加密算法 RSA 在長文本上的開銷。

4.2 對稱加密的 Message Digest

在數據通信階段,SSL/TLS 會對原始消息(message)做一次哈希,得到該消息 message 的摘要,稱爲消息摘要(Message Digest)。對端接受到消息後,使用協商出來的對稱加密密鑰解密數據包,得到原始消息 message;接着也做一次相同的哈希算法得到摘要,對比發送過來的消息摘要和計算出的消息摘要是否一致,可以判斷通信數據是否被篡改。

 


 

 

V. HTTPS 通信流程

到此,HTTPS 涉及到的關鍵問題基本都覆蓋了。本章總結整個 HTTPS 的通信過程:

補充說明幾點:

5.1 協商密鑰:客戶端/服務端隨機數、Client/Server Key

在加密一章節介紹的 ECDH 是停留在原理層面,實際中密鑰協商除了 PreMaster-Secret(即 Client/Server Key)之外,還有客戶端和服務端隨機數參與,參考文章《Https:TLS 握手協議》,引用文中的圖來自展示實際 ECDH 祕鑰協商的做法:

 

5.2 Change Cipher Spec

Change Cipher Spec是通知對方需要加密參數。文章《TLSde 改變密碼標準協議(Change Cipher Spec Protocol)》指出:

SSL 修改密文協議的設計目的是爲了保障 SSL 傳輸過程的安全性,因爲 SSL 協議要求客戶端或服務器端每隔一段時間必須改變其加解密參數。當某一方要改變其加解密參數時,就發送一個簡單的消息通知對方下一個要傳送的數據將採用新的加解密參數,也就是要求對方改變原來的安全參數。

SSL 修改密文協議是使用 SSL 記錄協議服務的 SSL 高層協議的 3 個特定協議之一,也是其中最簡單的一個。協議由單個消息組成,該消息只包含一個值爲 1 的單個字節。該消息的唯一作用就是使未決狀態複製爲當前狀態,更新用於當前連接的密碼組。爲了保障 SSL 傳輸過程的安全性,雙方應該每隔一段時間改變加密規範。

5.3 Encrypted Handshake Message

Encrypted Handshake Message作用就是確認協商出來的對稱加密密鑰 SK 的正確性,在客戶端和服務端協商得到對稱加密密鑰 SK 之後,互相給對方發了一條用 SK 加密的消息,如果這個加密的消息被解密校驗成功,那麼就說明對稱加密密鑰 SK 是正確的。

5.4 單向驗證和雙向驗證

本章全部所探討的案例都是基於單向驗證,即客戶端向服務端請求證書、驗證服務端身份。在一些實際場景中,對安全性的要求更高,有服務端要求驗證客戶端的身份,即雙向驗證。雙向驗證在單向驗證基礎上,增加“在服務端發送證書之後,向客戶端發送‘請求證書’請求,接着驗證客戶端身份”這個步驟。參考下圖(圖片出處不查):

 

 



 

VI. HTTPS 實戰問題記錄

問題:HTTPS 是否需要做域名劫持?

沒必要。

原因如下:https 在證書校驗這步,客戶端除了通過對比數字簽名來校驗證書的有效性,還會比較證書上的域名是否與自己要訪問的域名一致。因此,只要服務器的證書是可信的且客戶端不跳過“證書驗證”這個步驟,https 能夠防止域名劫持。

筆者在實際中做過防止域名劫持的工作,具體做法是:首先,客戶端向可信賴的域名服務器請求域名對應的 IP 地址;接着,客戶端用 IP 替換域名進行網絡請求。被稱爲HTTPS 的 IP 直連。但在實際中會遇到了一個問題:域名身份不對。根本解決方案是:1).書校驗時,選擇自己定義的 hostname 進行校驗;2).證書校驗前,把 URL 的 IP 替換回域名。在很多語言實現中,解決方案更爲簡單:在請求頭部的增加 host-name 字段,值填入域名即可。

問題:"x509: certificate signed by unknown authority"

這個問題是客戶端拿到了服務器的證書要進行身份驗證,但是通過證書信任鏈策略發現中間斷了,搜索不到根證書。說白了就是客戶端本地沒有簽發這個用戶證書的根證書或中介證書。

實際中的解決辦法有:1). 缺啥裝啥,沒有根證書/中介證書,那就安裝上;2).跳過證書身份驗證這步。GoLang 中跳過身份驗證的實現:

client := &http.Client{
    Transport: &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
}

 

問題:https 項目中,服務端怎麼管理證書和 RSA 密鑰?

看情況。

如果是正規的公司,一般會有統一的接入層幫忙做掉,後臺開發程序員只需要關心自己的業務邏輯即可。運維同事或者是負責接入層開發的同事們會定期更新證書,負責幫忙做 HTTPS 的 RSA 管理。而且這些證書都是由正規權威 CA 機構簽發的,普遍的客戶端設備上都預置了對應的根證書。
如果是個人,一般沒有條件負擔 HTTPS 證書費用,因此可以選擇自己簽發自簽證書,或者到免費的證書籤發機構申請證書。但是這類證書要求在客戶端上同步安裝對應的根證書。

 

問題:https 項目中,客戶端的根證書要提前安裝嗎?

上一個問題中已經提到了:

  • 如果是正規權威 CA 機構簽發的證書,一般不需要提前安裝;

  • 如果是私人簽發的證書,需要提前安裝。

但是,筆者在邊緣計算設備上開發時發現,比如攝像頭這類的“tinny os”上,是一個“閹割”版本的 Linux 系統,因此沒有安裝任何根證書。在這類設備上做 https 通信,一定需要提前安裝根證書才行。

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