
網(wǎng)絡(luò)安全篇,面對復雜多變的網(wǎng)絡(luò)環(huán)境,我們需要掌握哪些關(guān)于網(wǎng)絡(luò)安全的相關(guān)知識,聊一聊與網(wǎng)絡(luò)安全相關(guān)的:HTTPS、SSL、TLS 等。
網(wǎng)絡(luò)安全專題
- 網(wǎng)絡(luò)安全的基石
《網(wǎng)絡(luò)安全 — HTTPS》
《網(wǎng)絡(luò)安全的基石(上)— 加密》
《網(wǎng)絡(luò)安全的基石(下)— 完整性與身份認證》
《公鑰信任問題 — 數(shù)字證書與 CA》
《信任始于握手 — TLS 連接過程詳解》
- HTTPS 的優(yōu)化
《TLS 1.3 特性解析》
《如何優(yōu)化 HTTPS 連接》- 待完善
TLS 協(xié)議的組成
在介紹 TLS 握手之前,我們先來簡單介紹下 TLS 協(xié)議的組成。
TLS 實際由若干不同職責的模塊組成,比較常用的有握手協(xié)議、變更密碼規(guī)范協(xié)議、警報協(xié)議和記錄協(xié)議等。

從體系結(jié)構(gòu)圖可以看出,SSL/TLS 協(xié)議可分為兩層:握手協(xié)議和記錄協(xié)議。
握手協(xié)議
握手協(xié)議用來協(xié)商會話參數(shù)(如會話密鑰、應(yīng)用層協(xié)議等)。它實際由若干不同職責的子模塊組成,比較常用的有握手協(xié)議、變更密碼規(guī)范協(xié)議、警報協(xié)議和記錄協(xié)議等。
- 握手協(xié)議(Handshake Protocol)
建立在 SSL 記錄協(xié)議之上,是 TLS 里最復雜的子協(xié)議,要比 TCP 的 SYN/ACK 復雜的多。用于在實際傳輸數(shù)據(jù)之前,通訊雙方進行身份認證、協(xié)商加密算法、交換會話密鑰,用于后續(xù)的混合加密系統(tǒng)。
- 變更密碼規(guī)范協(xié)議(Change Cipher Spec Protocol)
是一個非常簡單的“通知”。用于告訴對方,后續(xù)的數(shù)據(jù)都將使用加密保護。那么反過來,在它之前,數(shù)據(jù)都是明文的。為了保障 SSL 傳輸過程的安全,客戶端和服務(wù)器雙方應(yīng)該每間隔一段時間改變加密規(guī)范。在客戶端和服務(wù)器完成握手協(xié)議之后,它需要向?qū)Ψ桨l(fā)送相關(guān)消息,通知對方隨后的數(shù)據(jù)將使用已協(xié)商的加密規(guī)范進行保護。
- 警報協(xié)議(Alert Protocol)
職責是向?qū)Ψ桨l(fā)出警報信息,類似于 HTTP 協(xié)議里的狀態(tài)碼。比如 protocol_version 就是不支持舊版本,bad_certificate 就是證書有問題,收到警報后另一方可以選擇繼續(xù),也可以立即終止連接。警報協(xié)議(Alert Protocol)的職責是向?qū)Ψ桨l(fā)出警報信息,類似于 HTTP 協(xié)議里的狀態(tài)碼。比如 protocol_version 就是不支持舊版本,bad_certificate 就是證書有問題,收到警報后另一方可以選擇繼續(xù),也可以立即終止連接。
記錄協(xié)議 (Record Protocol)
建立在可靠的傳輸協(xié)議(如 TCP)之上,為高層協(xié)議提供數(shù)據(jù)封裝、壓縮及加密等基本功能的支持。保證連接的機密性和完整性。所有的其他子協(xié)議都需要通過記錄協(xié)議發(fā)出。但多個記錄數(shù)據(jù)可以在一個 TCP 包里一次性發(fā)出,也并不需要像 TCP 那樣返回 ACK。
有關(guān) SSL 協(xié)議體系結(jié)構(gòu)的更詳細介紹你可以參考這篇文章。
SSL/TLS 在網(wǎng)絡(luò)模型中的位置
你是否有想過?在網(wǎng)絡(luò)通信模型中, TLS 協(xié)議是處在什么位置呢?下面我們通過一張圖來簡單了解下:

SSL/TLS 在網(wǎng)絡(luò)模型中屬于應(yīng)用層協(xié)議(實際在 OSI 的會話層),接管應(yīng)用層的數(shù)據(jù)加解密,并通過網(wǎng)絡(luò)層進行收發(fā)。
TLS 握手過程
下圖簡要描述了 TLS 的握手過程,其中每個“框”都是一個記錄,多個記錄組成一個 TCP 包發(fā)送。所以,最多要經(jīng)過 2 RTT(4 個消息)才可以完成握手,然后就可以在安全的通信環(huán)境里發(fā)送 HTTP 報文,實現(xiàn) HTTPS 協(xié)議。

TLS 握手總是以 ClientHello 消息開始,就跟 TCP 握手總是以 SYN 包開始一樣。
上面是相對簡要的握手過程,實際上關(guān)于 TLS 握手過程可以劃分為兩種方式:使用 RSA 做密鑰交換和 ECDHE 做密鑰交換。下面我們就詳細地介紹下它們的握手過程。
ECDHE 握手
在 TCP 成功建立連接之后,客戶端首先發(fā)送一個 “Client Hello” 消息,也就是跟服務(wù)器“打招呼”。

內(nèi)容包括:客戶端的版本號、支持的密碼套件,還有一個隨機數(shù)(Client Random),用于后續(xù)生成會話密鑰。
Handleshake Protocol: Client Hello
Version: TLS 1.2(0x0303)
Random:1cbf803321fd26234ds78sleds...
Cipher Suites(17 suites)
Cipher Suite:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
Cipher Suite:TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
...
可以看到 Client Hello 消息攜帶的相關(guān)信息,關(guān)鍵的隨機數(shù)需要保留著。
作為“禮尚往來”,服務(wù)器收到 “Client Hello” 后,會返回一個 “Server Hello” 消息。把 TLS 版本對一下,也會返回一個隨機數(shù)(Server Random),然后從客戶端的列表里選一個作為本次通信使用的密碼套件,如下選擇了 “TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384”。
Handshake Protocol: Server Hello
Version: TLS 1.2(0x0303)
Random: 0e6320f21bae50842e96…
Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
這個意思是:把版本好對上了,服務(wù)端在客戶端支持的密碼套件中選擇了一個合適的:橢圓曲線 + RSA、AES、SHA384。服務(wù)端也返回一個隨機數(shù),需要客戶端保留著。
然后,服務(wù)端為了證明自己的身份,就把證書也發(fā)給客戶端(Server Certificate 消息)。
接下來的關(guān)鍵操作,因為服務(wù)器選擇了 ECDHE 算法,所以它會在證書發(fā)送后發(fā)送 “Server Key Exchange” 消息,里面是橢圓曲線的公鑰(Server Params),用來實現(xiàn)秘鑰交換算法,再加上自己的私鑰簽名認證。
Handshake Protocol: Server Key Exchange
EC Diffie-Hellman Server Params
Curve Type: named_cure (0x03)
Named Curve: x25519 (0x001d)
Pubkey: 3b39deaf00217894e...
Signature Algorithm: rea_pkcs1_sha512 (0x0601)
Signature: 37141adac38ea4...
這一步相當于:服務(wù)端又給了一個算法參數(shù),和剛才的隨機數(shù)一樣需要客戶端保留,為了防止別人冒充,服務(wù)端用私鑰進行簽名。
之后的 “Server Hello Done” 消息,服務(wù)端的“打招呼”完畢。
此時第一個 RTT 就結(jié)束了(2 個 TCP 數(shù)據(jù)包),結(jié)果是客戶端和服務(wù)器通過明文共享了三個信息:Client Random、Server Random 和 Server Params。
客戶端也拿到了服務(wù)器的證書,那這個證書里的公鑰是否真實有效呢?回想下我們在上期《公鑰信任問題 — 數(shù)字證書與 CA》介紹的證書驗證過程,確認證書的真實性,再用證書公鑰驗證簽名,就確認了服務(wù)器的身份。
然后,客戶端按照密碼套件的要求,也生成一個橢圓曲線的公鑰(Client Params),用 “Client Key Exchange” 消息發(fā)給服務(wù)器。
Handshake Protocol: Client Key Exchange
EC Diffie-Hellman Client Params
Pubkey: 8c674d0e08dc27b5eaa…
現(xiàn)在客戶端和服務(wù)器都拿到了密鑰交換算法的兩個參數(shù)(Client Params、Server Params),就用 ECDHE 算法生成一個 “Pre-Master(預主密鑰,其實也是個隨機數(shù))”。
具體的計算過程和原理非常復雜,該計算能夠保證即使黑客截獲了之前的參數(shù),也是絕對算不出這個隨機數(shù)的。具體你可參考這篇介紹。
現(xiàn)在客戶端和服務(wù)器有了三個隨機數(shù):Client Random、Server Random、Pre-Master(預主密鑰)。然后通過它們生成加密會話的主密鑰 “Master-Secret”。由于黑客拿不到 “Pre-Master”,所以也就得不到主密鑰。
TLS 的設(shè)計考慮的非常全面,為了保證真正的“完全隨機和不可預測”,他們不信任客戶端或服務(wù)器的偽隨機數(shù)的可靠性,所以采用三個不可靠的隨機數(shù)混合起來,那么“隨機”的程度就非常高了,足夠讓黑客難以猜測。
生成的主密鑰為 48 字節(jié),但它還不是最終用于通信的會話密鑰,還會再用主密鑰派生出會話密鑰。到這一步 TLS 的握手就要結(jié)束了??蛻舳税l(fā)送一個 “Change Cipher Spec”,然后再發(fā)一個 “Finished” 消息,把之前所有發(fā)送的數(shù)據(jù)做個摘要,再加密一下,讓服務(wù)器做個驗證。
服務(wù)器也是同樣的操作,發(fā)送 “Change Cipher” 和 “Finished” 消息,雙方驗證加密解密 OK,握手正式結(jié)束,后面就開始收發(fā)被加密的 HTTP(Application Data)請求和響應(yīng)了。
RSA 握手過程
如今主流的 TLS 握手就是 ECDHE,整個過程可以說是夠復雜的。不過整個握手過程好像和其他的地方看到的不一樣呢?這與傳統(tǒng)的握手有 2 點不同:
使用 ECDHE 實現(xiàn)秘鑰交換,而不是 RSA,所以會在服務(wù)端發(fā)出“Server Key Exchange” 消息。
因為使用了 ECDHE,客戶端可以不用等到服務(wù)器發(fā)回 “Finished” 確認握手完畢,就立即發(fā)出 HTTP 報文了,節(jié)省了一個 RTT 時間。這個叫做 “TLS False Start”,意思就是“搶跑”,和 “TCP Fast Open” 有點像,都是不等連接完全建立就提前發(fā)送應(yīng)用數(shù)據(jù)來提高傳輸效率。
下面我們看下傳統(tǒng)的 TLS 握手過程:

大體流程沒有變,只是 “Pre-Master”(預主密鑰) 不再需要用算法生成,而是客戶端直接生成隨機數(shù),然后用服務(wù)器的公鑰,通過 “Client Key Exchange” 消息發(fā)給服務(wù)器。服務(wù)器再用私鑰解密,這樣雙方也實現(xiàn)了共享三個隨機數(shù),就可以生成主密鑰。
說道這里,TLS 的握手基本上就介紹完了。私鑰可以說是整個 TLS/SSL 協(xié)議中最重要的東西了,結(jié)合上面介紹的握手過程,我們再總結(jié)下兩種握手過程中私鑰所起到的作用。
ECDHE 握手時的私鑰用途
對于 ECDHE 來說,客戶端和服務(wù)端雙方交換的是橢圓曲線參數(shù),私鑰只是用來簽名,這是為了保證消息是持有私鑰者發(fā)送的,而非冒充的。雙方交換完參數(shù)之后生成預主密鑰,再生成主密鑰和會話密鑰(這里就和 RSA 后面的流程一樣了)。

RSA 握手時的私鑰用途
對于 RSA 來說,客戶端生成預主密鑰,然后用公鑰加密再發(fā)送給服務(wù)器,服務(wù)器得到預主密鑰,然后由預主密鑰生成主密鑰,再由主密鑰生成會話密鑰,最后用會話密鑰來通信。

可以看出 RSA 和 ECDHE 密鑰交換算法的私鑰用途是不一樣的,RSA 密鑰交換時私鑰用來解密,ECDHE 則是用來簽名。
SSL/TLS 中預主密鑰,主密鑰和會話密鑰
主密鑰是有預主密鑰、客戶端隨機數(shù)和服務(wù)端隨機數(shù)通過 PRF 函數(shù)生成的;會話密鑰是由主密鑰、客戶端隨機數(shù)和服務(wù)器隨機數(shù)聽過 PRF 函數(shù)生成的,會話密鑰里面包含對稱加密密鑰、消息認證和 CBC 模式的初始向量,但對于非 CBC 模式的加密算法來說,就沒有用到這個初始向量。

session 緩存和 session ticket 里面保存的主密鑰,而不是會話密鑰,這是為了保證每次會話都是獨立的,這樣才能安全。即使一個主密鑰泄露了也不影響其他會話。關(guān)于該部分將在后面的優(yōu)化部分再展開介紹。
雙向認證
大家平時在登錄網(wǎng)上銀行時,有時要使用 U 頓給用戶頒發(fā)客戶端證書。其實那就是雙向認證,即服務(wù)端驗證客戶端身份。
但是在生活中的絕大多數(shù)場景下,我們只是“單向認證” 的握手過程,只認證了服務(wù)器的身份,而沒有認證客戶端的身份。這是因為通常單向認證通過后已經(jīng)建立了安全通信,再配合賬號密碼等簡單的手段就能夠確認客戶端的真實身份。
雙向認證的流程也沒有發(fā)生太大的變化,只是在 “Server Hello Done” 之后,“Client Key Exchange” 之前,客戶端要發(fā)送 “Client Certificate” 消息,服務(wù)器收到后也把證書鏈走一遍,驗證客戶端的身份。
總結(jié)
今天我們主要介紹了 HTTPS/TLS 的握手,整個過程還是比較復雜的。不過為了方便記憶我們可以簡單總結(jié)為如下幾條:
HTTPS 協(xié)議在握手之前,需要先進行 TCP 握手,然后執(zhí)行 TLS 握手,才能建立安全連接;
TLS 握手的目的是安全地交換對稱密鑰(會話密鑰),這個過程需要三個隨機數(shù),第三個隨機數(shù) “Pre-Master” 必須加密傳輸,絕對不能讓黑客破解;
“Hello” 消息交換隨機數(shù),“Key Exchange” 消息交換 “Pre-Master”;
“Change Cipher Spec” 消息之前傳輸?shù)亩际敲魑?,之后都是通過對稱密鑰加密的密文。
網(wǎng)絡(luò)安全涉及了方方面面太多的知識,尤其是網(wǎng)絡(luò)的基礎(chǔ)知識對我們來說還是非常重要的,關(guān)于這部分大家又有什么要分享的?歡迎你的分享留言或指正。
網(wǎng)絡(luò)安全系列專題
- 網(wǎng)絡(luò)安全 — HTTPS
- 網(wǎng)絡(luò)安全的基石(上)— 加密
- 網(wǎng)絡(luò)安全的基石(下)— 完整性與身份認證
- 公鑰信任問題 — 數(shù)字證書與 CA
擴展閱讀