前一段時間在看X.509證書結構 與 TLS證書校驗鏈相關知識,到今天感覺基本了解清楚,想着寫一篇文章記錄學習心得。
在實際工作中,涉及到X.509證書結構與 TLS證書校驗鏈的場景便是 HTTPS 網絡請求。
這篇文章從HTTPS網絡請求開始,詳細介紹HTTPS秘鑰協商的詳細流程、TLS證書的校驗流程、TLS證書鏈的校驗流程。
- HTTPS
HTTPS簡介。 - TLS握手
HTTPS秘鑰協商流程詳細說明。 - TLS證書 校驗
- TLS證書鏈 校驗
一、HTTPS簡介
HTTPS (Secure Hypertext Transfer Protocol)安全超文本傳輸協議,是一種通過計算機網絡進行安全通信的傳輸協議。
HTTPS 利用 SSL/TLS 來加密數據包,經由 HTTP 進行通信。
其設計的主要目的是,提供對網站服務器的身份認證、保護交換數據的隱私與完整性。

TLS/SSL
TLS 與 SSL某種程度上指的是同一個概念:
SSL(Secure Socket Layer) 1994年由 瀏覽器開發商Netscape(美國網景通信公司) 率先倡導研發,為數據通訊提供安全支持,開發了最初的幾個版本SSL 1.0、SSL 2.0、SSL 3.0。TLS(Transport LayerSecurity)前身為SSL,1999年從 3.1 開始被IETF(Internet Engineering Task Force,Internet 工程任務組)標准化並改名,發展至今已經有 TLS 1.0、TLS 1.1、TLS 1.2 三個版本。
SSL3.0、TLS1.0由於存在安全漏洞,已經很少被使用到。TLS 1.3 因改動會比較大,目前尚處在草案階段。當前被廣泛使用的是是TLS 1.1、TLS 1.2;

如上圖所示,TLS/SSL是介於TCP和HTTP之間的一層安全協議。
HTTP
HTTP(HyperText Transfer Protocol)超文本傳輸協議。
HTTP是一個客戶端(用戶)和服務端之間請求和應答的標准,其最初的設計目的是為了提供一種發布和接收HTML頁面的方法。
注:Http協議不是本文重點,感興趣的同學可參考文章:
HTTP 協議詳解:
https://blog.csdn.net/xiaxl/article/details/104541274
二、SSL/TLS 握手
SSL/TLS握手過程 用一句話總結就是:用非對稱加密的手段傳遞密鑰,然后用密鑰進行對稱加密傳遞數據。
SSL/TLS握手,秘鑰協商的過程大致可分為以下幾個步驟:
- 1、Client Hello
Client——>Server 客戶端向服務端發送 Client Hello 消息。 - 2、Server Hello
Server——>Client 服務端向客戶端發送 Server Hello 消息。 - 3、Certificate
Server——>Client 服務端下發公鑰證書。 - 4、Server Key Exchange
Server——>Client 服務端下發秘鑰交換的額外數據。 - 5、Server Hello Done
Server——>Client 服務端握手信息發送完畢。 - 6、證書合法性校驗
Client 對 Server下發的公鑰證書進行合法性校驗。 - 7、協商加密秘鑰
Client——>Server 協商計算客戶端、服務端通信的加密秘鑰enc_key。 - 8、Change Cipher Spec Protocol
Server——>Client 服務端告知客戶端后續的通信都采用協商的秘鑰enc_key與算法進行加密通信。 - 9、Encrypted Handshake Message
Server——>Client 服務端用秘鑰enc_key加密,發出的第一條加密消息。 - 10、Application Data
Client——>Server SSL/TLS 握手完成,所有后續通信均 采用秘鑰enc_key加密。
SSL/TLS握手,秘鑰協商的流程圖 如下圖所示:

這里以客戶端向百度主頁發起Https請求為例,用 Wireshark抓包 對SSL/TLS握手的各個環節進行介紹,抓包示意圖如下圖所示:

2.1、Client Hello
Client Hello( Client——>Server ): 客戶端向服務端發送 Client Hello 消息。
消息中包含客戶端的 TSL版本信息、秘鑰隨機數、加密套件候選列表、壓縮算法候選列表、擴展字段等信息,相關信息抓包如下:

各字段詳細描述如下:
- Version : 支持的最高TSL協議版本,從低到高依次 SSLv2 SSLv3 TLSv1 TLSv1.1 TLSv1.2;
- Random:隨機數
random_C用於后續的密鑰協商; - Session ID:有或者無,有則客戶端傳上一次session的id可以恢復session;
- Cipher Suite:客戶端支持的密碼算法列表,供服務器選擇;
- Compression Methods:客戶端支持的壓縮算法列表,用於后續的信息壓縮傳輸;
- extensions:擴展字段;
2.2、Server Hello
Server Hello( Server——>Client ): 服務端向客戶端發送 Server Hello 消息。
消息中包括服務端選擇使用的TSL協議版本、選擇的加密套件、選擇的壓縮算法、服務端生成的隨機數等,相關信息抓包如下:

- Version:服務器選擇的版本;
- Random:隨機數
random_S用於后續的密鑰協商; - Session ID:有或者無,有則客戶端傳上一次session的id可以恢復session;
- Cipher Suite:服務端選擇的密鑰算法;
- Compression Methods:服務端選擇的壓縮算法;
注:到此 客戶端 和 服務端 都擁有了兩個隨機數(random_C+ random_S),這兩個隨機數會在后續生成對稱秘鑰時會用到。
2.3、Certificate
Certificate( Server——>Client ): 服務端下發公鑰證書給客戶端。相關信息抓包如下:

Certificate:服務端的公鑰證書;
注:Certificate 公鑰證書的詳細結構會在下文進行詳細舉例說明。
2.4、Server Key Exchange
Server Key Exchange( Server——>Client ): 該消息的目的是 攜帶密鑰交換的額外數據。

該消息內容對於不同的協商算法套件會存在差異:
- 對於使用DHE/ECDHE非對稱密鑰協商算法的SSL握手,服務器發送其使用的DH參數;
- RSA算法不會繼續該握手流程(DH、ECDH也不會發送server key exchange)。
2.5、Server Hello Done
Server Hello Done( Server——>Client ):
通知客戶端,Server端已經將所有握手消息發送完畢。

2.6、證書校驗
客戶端拿到服務端的公鑰證書后,需對該證書的合法性進行校驗。校驗內容如下:
- 證書鏈的可信性;
- 證書是否吊銷;
- 證書有效期;
- 證書域名校驗,核查證書域名是否與當前的訪問域名匹配;
注:證書的詳細校驗過程將在下文進行詳細介紹
2.7、協商加密秘鑰
Client——>Server: 這一步包含三個步驟,主要是 協商計算客戶端、服務端通信的加密秘鑰。

- Client Key Exchange
證書合法性驗證通過之后,客戶端產生隨機數字Pre-master。
計算生成秘鑰enc_key{ enc_key=Fuc(random_C, random_S, Pre-Master) } 。
將Pre-master與enc_key用證書公鑰加密(非對稱加密算法)發送給服務端; - Change Cipher Spec Protocol
客戶端通知服務端后續的通信都采用協商的密鑰enc_key和加密算法進行加密通信; - Encrypted Handshake Message
客戶端:客戶端將之前所有的握手數據(包括接受、發送)生成摘要;然后用秘鑰enc_key加密(對稱加密算法),發送給對應的服務端。
服務端:服務端收到消息后,會用秘鑰enc_key解密客戶端的摘要信息;然后用與客戶端相同的算法生成服務端摘要信息,最后對比兩個摘要信息相同,則驗證通過。
2.8、Change Cipher Spec Protocol
Change Cipher Spec Protocol( Server——>Client ): 服務器同樣發送 Change Cipher Spec Protocol 以告知客戶端后續的通信都采用協商的秘鑰enc_key與算法進行加密通信;

2.9、Encrypted Handshake Message
Encrypted Handshake Message( Server——>Client ):
服務端:服務端會將握手過程的消息生成摘要再用秘鑰enc_key加密,這是服務端發出的第一條加密消息;
客戶端:客戶端接收后會用秘鑰enc_key解密,能解出來說明協商的秘鑰是一致的。

2.10、Application Data ( Client——>Server )
Application Data Client——>Server ): 雙方已安全地協商出了同一份秘鑰enc_key,所有的應用層數據都會用這個秘鑰加密后再通過 TCP 進行可靠傳輸。

2.11 總結
SSL/TLS握手協商:用非對稱加密的手段傳遞密鑰,然后用密鑰進行對稱加密傳遞數據。
三、證書校驗
這一節對前文 2.6證書校驗提到的證書校驗流程進行詳細介紹:
- 1、X.509數字證書結構舉例
- 2、客戶端 如何校驗服務端下發的公鑰證書?
3.1、X.509數字證書
了解證書校驗原理之前,先認識一下X.509證書的結構。
X.509是密碼學里公鑰證書的格式標准,當前X.509證書已應用在包括TLS/SSL在內的眾多網絡協議里。
一個具體的X.509 v3數字證書結構大致如下 :
// X.509數字證書
Certificate
// 版本號
Version Number
// 序列號
Serial Number
// 證書簽名算法ID
Signature Algorithm ID
// 證書發行者
Issuer Name
// 證書有效時間
Validity period
// 證書主體名稱
Subject name
// 證書主體公鑰信息
Subject Public Key Info
// 證書公鑰算法
Public Key Algorithm
// 證書公鑰
Subject Public Key
// 發行商唯一ID
Issuer Unique Identifier (optional)
// 主體唯一ID
Subject Unique Identifier (optional)
// 擴展
Extensions (optional)
// 證書簽名算法
Certificate Signature Algorithm
// 證書簽名值
Certificate Signature
這里以百度的Tls證書進行舉例:


Certificate:
Data:
Version: 3 (0x2)
Serial Number:
72:58:78:36:6e:9f:56:e8:1d:41:88:48
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=BE, O=GlobalSign nv-sa, CN=GlobalSign Organization Validation CA - SHA256 - G2
Validity
Not Before: Apr 2 07:04:58 2020 GMT
Not After : Jul 26 05:31:02 2021 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
Public-Key: (2048 bit)
Modulus:
00:c1:a9:b0:ae:47:1a:d2:57:eb:1d:15:1f:6e:5c:
b2:e4:f8:0b:20:db:ea:00:df:29:ff:a4:6b:89:26:
4b:9f:23:2f:ec:57:b0:8a:b8:46:40:2a:7e:bc:dc:
5a:45:97:4f:ad:41:0e:bc:20:86:4b:0c:5d:55:21:
47:e2:31:3c:57:a7:ec:99:47:eb:47:0d:72:d7:c8:
16:54:75:ef:d3:45:11:0f:4b:ce:60:7a:46:5c:28:
74:ae:8e:1b:be:d8:70:66:7b:a8:93:49:28:d2:a3:
76:94:55:de:7c:27:f2:0f:f7:98:0c:ad:86:da:c6:
ae:fd:9f:f0:d9:81:32:9a:97:e3:21:ee:04:92:96:
e4:78:11:e5:c4:10:0e:10:31:7a:4a:97:a0:eb:c7:
9b:c4:da:89:37:a9:c3:37:d7:56:b1:7f:52:c7:d9:
26:0a:d6:af:38:16:b1:6d:fb:73:79:b1:68:79:03:
90:eb:88:7b:8c:48:91:98:51:a5:07:94:86:a5:78:
46:79:8f:58:9b:e9:35:59:a7:f1:7b:57:31:0a:90:
cf:24:ce:0d:24:e7:92:b2:6a:e9:e6:96:37:0a:b8:
7c:87:2f:74:d2:5c:e8:4b:0a:5f:66:18:a7:41:86:
cf:26:a6:08:8e:a5:49:17:92:53:b3:91:a5:cf:53:
b0:31
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
Authority Information Access:
CA Issuers - URI:http://secure.globalsign.com/cacert/gsorganizationvalsha2g2r1.crt
OCSP - URI:http://ocsp2.globalsign.com/gsorganizationvalsha2g2
X509v3 Certificate Policies:
Policy: 1.3.6.1.4.1.4146.1.20
CPS: https://www.globalsign.com/repository/
Policy: 2.23.140.1.2.2
X509v3 Basic Constraints:
CA:FALSE
X509v3 CRL Distribution Points:
Full Name:
URI:http://crl.globalsign.com/gs/gsorganizationvalsha2g2.crl
X509v3 Subject Alternative Name:
DNS:baidu.com, DNS:baifubao.com, DNS:www.baidu.cn, DNS:www.baidu.com.cn, DNS:mct.y.nuomi.com, DNS:apollo.auto, DNS:dwz.cn, DNS:*.baidu.com, DNS:*.baifubao.com, DNS:*.baidustatic.com, DNS:*.bdstatic.com, DNS:*.bdimg.com, DNS:*.hao123.com, DNS:*.nuomi.com, DNS:*.chuanke.com, DNS:*.trustgo.com, DNS:*.bce.baidu.com, DNS:*.eyun.baidu.com, DNS:*.map.baidu.com, DNS:*.mbd.baidu.com, DNS:*.fanyi.baidu.com, DNS:*.baidubce.com, DNS:*.mipcdn.com, DNS:*.news.baidu.com, DNS:*.baidupcs.com, DNS:*.aipage.com, DNS:*.aipage.cn, DNS:*.bcehost.com, DNS:*.safe.baidu.com, DNS:*.im.baidu.com, DNS:*.baiducontent.com, DNS:*.dlnel.com, DNS:*.dlnel.org, DNS:*.dueros.baidu.com, DNS:*.su.baidu.com, DNS:*.91.com, DNS:*.hao123.baidu.com, DNS:*.apollo.auto, DNS:*.xueshu.baidu.com, DNS:*.bj.baidubce.com, DNS:*.gz.baidubce.com, DNS:*.smartapps.cn, DNS:*.bdtjrcv.com, DNS:*.hao222.com, DNS:*.haokan.com, DNS:*.pae.baidu.com, DNS:*.vd.bdstatic.com, DNS:click.hm.baidu.com, DNS:log.hm.baidu.com, DNS:cm.pos.baidu.com, DNS:wn.pos.baidu.com, DNS:update.pan.baidu.com
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Authority Key Identifier:
keyid:96:DE:61:F1:BD:1C:16:29:53:1C:C0:CC:7D:3B:83:00:40:E6:1A:7C
X509v3 Subject Key Identifier:
......
3.2、證書校驗
客戶端驗證服務端下發的證書,主要包括以下幾個方面:
- 1、校驗證書是否是
受信任的CA根證書頒發機構頒發; - 2、校驗證書是否在上級證書的
吊銷列表; - 3、校驗證書
是否過期; - 4、校驗證書
域名是否一致。
3.2.1、證書可信性
校驗證書是否可信:
校驗證書是否是由受信任的CA根證書頒發機構頒發。
為了確保客戶端獲取到的服務端公鑰不被篡改,需引入權威的第三方CA機構。
CA機構負責核實公鑰擁有者信息、頒發證書(對服務端公鑰進行簽名)、同時為使用者提供證書驗證服務。

CA機構 頒發證書的基本原理:
服務端生成一對公鑰、私鑰。服務端將自己的公鑰提供給CA機構。CA機構核實服務端公鑰擁有者信息:
核實申請者提供信息的真實性:如組織是否存在、企業是否合法、是否擁有域名的所有權等。CA機構簽發證書:
CA機構 計算 服務器公鑰摘要信息,然后利用CA機構私鑰(CA機構有一對公鑰、私鑰)加密摘要信息。
加密后的包含加密摘要信息的服務端公鑰即CA機構頒發的證書。
客戶端 驗證服務端公鑰的基本原理為:
客戶端獲取到服務端的公鑰:
Https請求 TLS握手過程中,服務器公鑰會下發到請求的客戶端。客戶端用存儲在本地的CA機構的公鑰,對服務端公鑰中對應的摘要信息進行解密,獲取到服務端公鑰的摘要信息A;客戶端根據對服務端公鑰進行摘要計算,得到摘要信息B;對比摘要信息A與B,相同則證書驗證通過;
3.2.2、證書吊銷
CA機構能夠簽發證書,同樣也存在機制宣布以往簽發的證書無效。若證書的申請主體出現:私鑰丟失、申請證書無效等情況,CA機構需要廢棄該證書。
主要存在兩類機制:CRL 與 OCSP。
- CRL(Certificate Revocation List)
證書吊銷列表:是一個單獨的文件,該文件包含了 CA機構 已經吊銷的證書序列號與吊銷日期;
證書中一般會包含一個 URL 地址CRL Distribution Point,通知使用者去哪里下載對應的 CRL 以校驗證書是否吊銷。
該吊銷方式的優點是不需要頻繁更新,但是不能及時吊銷證書,因為 CRL 更新時間一般是幾天,這期間可能已經造成了極大損失。 - OCSP(Online Certificate Status Protocol)
證書狀態在線查詢協議:一個實時查詢證書是否吊銷的方式。
請求者發送證書的信息並請求查詢,服務器返回正常、吊銷或未知中的任何一個狀態。
證書中一般也會包含一個 OCSP 的 URL 地址,要求查詢服務器具有良好的性能。
部分 CA 或大部分的自簽 CA (根證書)都是未提供 CRL 或 OCSP 地址的,對於吊銷證書會是一件非常麻煩的事情。
3.2.3、證書過期
校驗證書的有效期是否已經過期:主要判斷證書中Validity period字段是否過期。
3.2.4、證書域名
校驗證書域名是否一致:核查 證書域名是否與當前的訪問域名 匹配。
舉例中:
我們請求的域名 www.baidu.com 是否與證書文件中DNS標簽下所列的域名相匹配;
一種錯誤的寫法:
Android 軟件開發中,我們經常會遇到以下代碼,用來忽略證書的域名驗證,其實這是一種不安全的寫法:
// 對於自簽名證書,用以下代碼來忽略證書的域名驗證
HostnameVerifier hostnameVerifier = new HostnameVerifier() {
@Override
public boolean verify(String urlHostName, SSLSession session) {
// 忽略證書的域名驗證
return true;
}
};
四、證書鏈校驗
上一節介紹證書校驗場景,適用於服務器證書的簽發機構就是Ca機構。
實際證書申請中,由於權威的CA機構數量不多,若所有的服務器證書都向權威CA機構申請,那么CA機構的工作量就會非常大。因此CA機構采取授權 二級機構的方式來管理證書申請,經授權的二級機構也可以簽發服務器證書。

4.1、證書鏈校驗
證書簽發:
根證書CA機構 使用自己的私鑰對中間證書進行簽名,授權中間機構證書;中間機構使用自己的私鑰對服務器證書進行簽名,從而授權服務器證書。
證書校驗:
客戶端通過服務器證書中簽發機構信息,獲取到中間證書公鑰;利用中間證書公鑰進行服務器證書的簽名驗證。
a、中間證書公鑰解密 服務器簽名,得到證書摘要信息;
b、摘要算法計算 服務器證書 摘要信息;
c、然后對比兩個摘要信息。客戶端通過中間證書中簽發機構信息,客戶端本地查找到根證書公鑰;利用根證書公鑰進行中間證書的簽名驗證。

4.2、中間證書怎么獲取?
這里可能大家有一個疑問,根證書是內置在終端設備上或瀏覽器中的,那中間機構證書怎么獲取?
這里仍以百度的Tls證書進行舉例,百度服務器證書 簽發者公鑰(中間機構公鑰)通過下圖中的URI獲取:

五、參考
TSL標准:
https://tools.ietf.org/html/rfc5246
X.509標准:
https://datatracker.ietf.org/doc/html/rfc5280
SSL/TSL 原理:
https://www.cnblogs.com/chenjingquan/p/10531305.html
TLS/SSL握手過程:
https://blog.csdn.net/hherima/article/details/52469674
= THE END =

