假如讓你來設計 SSL-TLS 協議
前言
說起網絡通信協議,相信大家對 TCP 和 HTTP 都很熟悉,它們可以說是當今互聯網通信的基石。但是,在網絡安全方面,它們卻是有着很大安全風險:
-
竊聽風險。第三方攻擊者可以隨意竊聽通信內容,比如獲取支付賬號密碼。
-
冒充風險。第三方攻擊者可以冒充他人身份與你通信,比如冒充銀行網站以竊取銀行賬號密碼。
-
篡改風險。第三方攻擊者可以隨意修改通信內容,比如在響應上加入釣魚網址。
爲此,SSL/TLS 協議應運而生。SSL/TLS 是建立在傳輸層之上、應用層之下的安全通信協議,它主要的設計意圖就是消除上述幾種安全風險,保證網絡通信安全。我們熟知的 HTTPS 就是 HTTP + SSL/TLS 構建的,可以說 SSL/TLS 是當今互聯網安全通信的基石。
那麼,現在假如讓你來設計 SSL/TLS 協議,你會怎麼設計呢?
本文將從設計者的視角介紹如何一步步設計出一個簡易版的 SSL/TLS 的過程,在文章的最後,再簡單介紹 TLS 1.2 版本的工作機制,以此幫助大家對 SSL/TLS 協議的基本原理有一個更深入的理解。
基於對稱加密算法的數據加密
竊聽風險主要是因爲通信雙方在網絡上明文傳輸數據,導致攻擊者可以通過簡單網絡抓包就能獲取到通信的內容。
要解決竊聽風險,就最好的方法就是對數據進行加密。也即客戶端在把數據發送出去之前,先對數據進行加密;服務端收到密文之後,再進行解密還原數據。這樣就能避免在網絡上傳播明文,從而可以防止第三方攻擊者的竊聽。
提到加密算法,很多人首先會想到對稱加密算法,它以簡單和高效著稱。對稱加密指的是加密和解密都使用同一份密鑰,常見的算法有 DES、AES 等。
現在,我們試着使用對稱加密算法來實現安全通信:
使用對稱密鑰加密的前提是,通信雙方都必須用同一份密鑰來對數據進行加密。主要有線下和線上密鑰交換兩種方案可以達到該目的:
-
線下密鑰交換,也即通信雙方線下約定好當面交換密鑰(比如通過 U 盤作爲媒介)。該方案可以保證密鑰交換的安全性,但是很難推廣使用。因爲在絕大多數場景中,客戶端和服務端都不可能碰面。
-
線上密鑰交換,也即通過網絡來傳輸密鑰。但在網絡明文傳輸密鑰同樣也會被攻擊者攔截,這樣的加密也沒有意義了。
因此,單純的對稱加密並不能滿足通信安全的要求,我們還要繼續優化......
基於非對稱加密算法的數據加密
非對稱加密算法指的是加密和解密使用不同的密鑰,這兩個不同的密鑰組成一個密鑰對,也即公鑰和私鑰。公鑰是公開的密鑰,所有人都能獲取到;私鑰則是保密的。當我們使用公鑰對數據進行加密後,只有對應的私鑰才能完成解密。常見的非對稱加密算法有 RSA、ECC 等。
現在,我們試着使用非對稱加密算法來實現安全通信:
通過非對稱加密算法,我們既能實現對數據的加密,又能解決密鑰交換的問題,從而消除了竊聽風險。但是,非對稱加密算法最大的缺點,就是加解密速度很慢,相比於對稱加密算法要慢 1000 多倍。因此,非對稱加密算法通常只適用於對少量數據的加密。
到目前爲止,單純地使用對稱加密算法或非對稱加密算法都無法滿足要求,還需要繼續優化......
基於對稱加密 + 非對稱加密算法的數據加密
既然對稱加密算法加解密速度快,但存在密鑰交換的問題;而非對稱加密算法可以解決密鑰交換問題,但加解密速度慢。那麼我們可以把兩種算法結合起來,也即通過對稱加密算法進行數據加密,在交換對稱密鑰時,使用非對稱加密算法來加密對稱密鑰,確保密鑰在網絡傳輸過程中不會被攻擊者竊聽。
現在,我們試着使用對稱加密 + 非對稱加密算法來實現安全通信:
使用對稱加密 + 非對稱加密算法的方案,我們消除了竊聽風險,也不會存在加解密性能問題,但是還是無法消除冒充風險。
考慮如下場景:
-
攻擊者把服務端的公鑰攔截,並保存下來。
-
攻擊者僞造成服務端,把自己的公鑰發送給客戶端。
-
攻擊者攔截使用非法公鑰加密後的對稱密鑰,解密後得到對稱密鑰明文,並保存下來
-
攻擊者使用服務端公鑰重新加密對稱密鑰,僞造成客戶端發送給服務端。
這番操作後,攻擊者就能在客戶端和服務端都不知情的情況下,得到了對稱密鑰。在這種場景下,攻擊者從被動攻擊的竊聽,轉爲主動攻擊的冒充,讓客戶端和服務端都誤以爲一直在跟對方通信。
因此,我們需要找到一種方法,讓客戶端能夠確保自己收到的公鑰,一定是真實的服務端發送過來的,也即能夠認證 “服務端” 的真實身份......
基於 CA 證書的身份認證
數字證書概述
引用百度百科的定義:
數字證書是指在互聯網通訊中標誌通訊各方身份信息的一個數字認證,人們可以在網上用它來識別對方的身份。
數字證書(Digital Certificate)就好比現實世界中的身份證,用於標識一個網絡用戶(人、公司、服務器等)的合法身份。就像身份證必須由公安局來頒發,可信的數字證書也必須由一個權威機構來頒發,該機構就是證書授權中心(Certificate Authority,CA),CA 頒發的數字證書我們通常稱作 CA 證書。
一個 CA 證書主要包含申請者的公鑰、申請者的信息、簽發機構 CA 的信息、有效時間、證書序列號等明文信息,同時也包含一個 CA 的數字簽名,正是該簽名的存在才證明了該證書的有效性。
數字簽名建立在非對稱加密算法的基礎上,CA 在頒發證書時,會先將證書的明文信息用指定的算法(比如 SHA256 算法)計算出一個數字摘要,再使用 CA 的私鑰對摘要進行加密,形成簽名。
而證書的驗證主要包含如下兩部分:
-
檢查證書的明文信息是否有效,比如證書是否過期、域名是否一致等。
-
用 CA 公佈的公鑰對證書籤名進行解密,得到
數字摘要1
。再使用同樣的算法對證書明文信息計算得出數字摘要2
。對比數字摘要1
和數字摘要2
是否相等。
頒發證書的機構並非只有一個,比如機構 A 可以用 CA 頒發的根證書去給機構 B 頒發二級證書;機構 B 又可以用二級證書去給機構 C 頒發三級證書,以此類推,也即所謂的證書鏈。
使用 CA 證書認證通信雙方的身份
現在,我們加入 CA 證書來認證通信雙方的身份:
引入 CA 證書之後,服務端的公鑰就放在它提供的證書之中,當客戶端驗證服務端證書通過後,也就說明其中的公鑰確實是來自服務端的合法公鑰。這樣,後續的通信流程就可以正常地進行了。
然而,如果對稱密鑰一直不變的話,攻擊者還是很有可能暴力破解出對稱密鑰。因此,我們還需要最好能夠實現每次連接的對稱密鑰都是不同的......
使用隨機數來生成對稱密鑰
爲了使每次連接的對稱密鑰都不同,我們可以引入隨機數來生成對稱密鑰,保證它的隨機性。但是,考慮到當前計算機生成的隨機數都是僞隨機數,爲了進一步提升隨機性,我們可以通過生成多個隨機數來達到此目的。
我們可以這麼設計:
-
客戶端和服務端先各生成一個隨機數(
隨機數1
和隨機數2
),在ClientHello
和ServerHello
報文中完成交換。 -
客戶端在驗證完服務端的身份後,再生成
隨機數3
,通過服務端的公鑰加密發給服務端。(此時,通信雙方都擁有了 3 個一樣隨機數) -
客戶端和服務端再根據這 3 個隨機數,生成最終的對稱密鑰。
這樣通過 3 個隨機數來生成的密鑰,就能較好地保證了密鑰的隨機性,降低被攻擊者破解的可能。
雖然
隨機數1
和隨機數2
是明文傳輸,但隨機數3
是密傳輸,也就能夠保證攻擊者很難破解到密鑰。
到目前爲止,我們已經通過多種手段成功阻止了攻擊者竊聽客戶端和服務端之間的通信內容。但是,如果攻擊者並不以竊聽通信內容爲目的,而是單純地想搞破壞。比如,攻擊者攔截了 ClientHello
報文,把其中的隨機數1
改成了隨機數4
,這樣就會導致客戶端和服務端生成的密鑰不一致。在此場景下,雖然連接已經建立起來了,但是客戶端和服務端還是無法正常地通信:
爲此,我們需要一種機制,校驗連接建立階段(握手階段)所有消息的正確性,防止建立錯誤的連接......
校驗握手消息的正確性
我們可以利用數字摘要來校驗所有握手消息的正確性,也即,在握手階段的最後,通信雙方都通過 Hash 算法(比如 SHA256)對自己收到的和發送的所有消息計算出數字摘要
,然後使用前面協商好的對稱密鑰對該數字摘要
進行加密,發送給對方。
當收到對方發過來的數字摘要
密文後,先用對稱密鑰對其進行解密,如果解密成功,說明密鑰生成沒問題;接着對比雙方的數字摘要
是否一致,如果一致,說明握手階段的消息沒有被篡改過,也即可以建立起正確的連接了。
到現在,我們基本上已經消除了竊聽風險(通過數據加密)、冒充風險(通過證書認證)和篡改風險(通過數字摘要)。但是,爲了建立起安全通信通道,我們需要經歷多次消息交互、加解密、身份認證等步驟,對性能有一定的損耗。
因爲經歷過一次握手之後,密鑰已經協商好,並且雙方都保存了下來。下次連接建立時,完全可以沿用上次握手協商好的密鑰,從而避免了重新協商密鑰,提升了性能。我們需要一種重用會話的機制來提升協議的性能......
重用會話來提升性能
爲了達到沿用上次協商好的密鑰的目的,我們爲每次連接都分配一個會話 ID。
-
在初次創建連接時,由服務端生成,並通過
ServerHello
返回給客戶端。 -
在下一次創建連接時,客戶端通過
ClientHello
把該會話 ID 發給服務端,表示希望重用該會話。 -
服務端在收到該會話 ID 後,就可以發送
Finished
消息,表示同意了會話重用,也即可以沿用上次會話協商好的密鑰進行安全通信了。
到這裏,我們已經完成了一個簡易版的 SSL/TLS 協議的設計,真實的 SSL/TLS 協議當然沒這麼簡單,但是裏面的核心思想和基本原理都是類似的。只是 SSL/TLS 爲了更好的安全性、擴展性和易用性等增加了一些機制,比如支持多種加密算法、使用 MAC 替代普通的數字摘要完成完整性校驗。
下面,我們將簡單介紹真實的 SSL/TLS 協議的工作機制。
SSL/TLS 協議機制概述
SSL 協議(Secure Sockets Layer)是 TLS(Transport Layer Security)協議的前身,它們的版本演進如下,當前最新的版本爲 TLS 1.3 版本。本節,我們將以當前使用最廣泛的 TLS 1.2 版本作爲分析對象,介紹 SSL/TLS 的基本工作機制。
SSL 1.0 版本 -> SSL 2.0 版本 -> SSL 3.0 版本 -> TLS 1.0 版本 -> TLS 1.1 版本 -> TLS 1.2 版本 -> TLS 1.3 版本
SSL/TLS 協議總覽
SSL/TLS 協議位於網絡協議棧中傳輸層和應用層之間,它內部又可以分爲 2 層,總共 5 種子協議:
Record 協議
最底層的 Record 協議負責對上層子協議的封裝,提供安全通信的能力:
-
私密連接。使用對稱加密算法(比如 AES、RC4 等)來加密數據,而且在每次連接中,通信雙方協商出來的加密密鑰都是不同的,以此達到更好的安全性。另外,Record 協議也可以提供不加密的封裝,比如在握手階段的 Hello 報文。
-
可靠連接。使用 MAC(Message Authentication Code,消息驗證碼,TLS 目前使用的 HMAC 也屬於 MAC 的一種)爲數據提供完整性校驗。同樣,在握手階段也可以不使用該功能。
Handshake 協議
上層的 Handshake 協議用在握手階段,爲通信雙方提供身份認證、加密算法和密鑰協商的能力:
-
身份認證。基於 CA 證書完成對端的身份認證,其中用到了非對稱加密技術(比如 RSA、DES 等)。該功能是可選的,但通常的做法是至少進行單向認證。
-
安全參數的協商。完成用於安全參數的協商(比如加密算法、哈希算法、密鑰等),並且能夠保證在協商過程中,攻擊者無法獲取密鑰。
-
可靠協商。確保在安全參數等協商過程中,攻擊者無法對報文實施篡改。
Handshake 協議包含了如下幾種報文類型:ClientHello
、SeverHello
、Certificate
、ServerKeyExchange
、CertificateRequest
、ServerHelloDone
、ClientKeyExchange
、CertificateVerify
、ChangeCipherSpec
、Finished
。
Change Cipher Spec 協議
Change Cipher Spec 協議也用在握手階段,當通信的一方發出 Change Cipher Spec 報文時,就表示密鑰已經協商好,從下一條消息開始,使用該密鑰來進行加密傳輸。
Alert 協議
Alert 協議只有在連接異常時纔會用上,當前協議定義的 Alert 消息類型如下:
close_notify: 表示發送方不會再發送任何消息,用於正常關閉連接,類似於TCP中的FIN報文
unexpected_message: 收到不在預期之內的消息
bad_record_mac: 收到的消息中MAC不正確,表示消息已經被篡改過
decryption_failed_RESERVED: 解密失敗,用於TLS的早期版本
record_overflow: 消息長度溢出,密文長度不超過2^14+2048字節;壓縮後的明文不超過2^14+1024字節
decompression_failure: 使用壓縮功能時,解壓失敗
handshake_failure: 握手階段無法協商出正確的安全參數
no_certificate_RESERVED: 爲了兼容SSL 3.0版本,TLS不再使用
bad_certificate: 證書籤名認證失敗
unsupported_certificate: 收到不支持的證書類型
certificate_revoked: 收到被廢棄的證書
certificate_expired: 收到過期的證書
certificate_unknown: 除上述4種情況外,其他證書異常場景
illegal_parameter: 握手階段報文的參數非法,比如範圍溢出等
unknown_ca: 不可信任的CA頒發的證書
access_denied: 證書校驗通過,但發送方卻拒絕繼續握手
decode_error: 消息解碼失敗
decrypt_error: 握手階段安全相關的步驟失敗,比如簽名校驗失敗、Finished消息校驗失敗等
export_restriction_RESERVED: 早期的TLS版本使用
protocol_version: 協議版本不支持
insufficient_security: 服務端要求的安全算法,客戶端無法滿足
internal_error: 協議內部錯誤
user_canceled: 用戶非正常主動關閉連接
no_renegotiation: 拒絕重新握手
unsupported_extension: 不支持的擴展
Application Data 協議
Application Data 協議用在通信階段,封裝了應用層的數據,經由 Record 協議封裝之後,通過 TCP 協議轉發出去。
SSL/TLS 協議的握手過程
第一次握手
- 客戶端向服務端發送
ClientHello
報文發起連接建立,其中攜帶了如下內容:
-
Version: 客戶端支持的 TLS 協議版本
-
Random: 客戶端生成的隨機數,隨後用於生成 master secret
-
SessionID: 會話 ID,如果不爲空,表示客戶端想重用該會話
-
CipherSuites: 客戶端支持的加密套件列表,在 SessionID 爲空時必須攜帶
-
CompressionMethods: 客戶端支持的壓縮算法列表
-
Extensions: 擴展內容
第二次握手
- 服務端向客戶端發送
ServerHello
報文,其中攜帶了如下內容:
-
Version: 選定的 TLS 版本,選擇通信雙方都支持的最高版本
-
Random: 服務端生成的隨機數,隨後用於生成 master secret
-
SessionID: 會話 ID,如果爲空,表示服務端開啓新的會話,並且不希望被重用;如果與客戶端帶過來的 SessionID 一樣,表示重用該會話;否則,開啓一個新的會話,並且在未來可能會被重用
-
CipherSuite: 選定的加密套件
-
CompressionMethod: 選定的壓縮算法
-
Extensions: 擴展內容
-
服務端向客戶端發送
Certificate
報文,其中攜帶了服務端的證書,證書必須是 x.509 標準格式,包含服務端公鑰、服務端域名、簽發方信息、有效期等信息。可選,客戶端需要通過證書來認證服務端身份時發送
-
服務端向客戶端發送
Server Key Exchange
報文,其中攜帶了客戶端用於生成 premaster secret 的安全參數。可選,當
Certificate
報文中攜帶的信息無法支撐客戶端生成 premaster secret 時發送 -
服務端向客戶端發送
CertificateRequest
報文,索求客戶端證書,其中包含了期望的證書類型、簽名算法和 CA 列表。可選,開啓雙向認證時發送
-
服務端向客戶端發送
ServerHelloDone
報文,表示當前服務端已經把所有與密鑰交換相關的內容都發送完畢。
第三次握手
-
客戶端向服務端發送
Certificate
報文,其中攜帶了客戶端證書。可選,收到服務端的
CertificateRequest
報文時發送 -
客戶端向服務端發送
ClientKeyExchange
報文,其中包含了使用服務端公鑰加密後的 premaster secret (隨機數),隨後用於生成 master secret。 -
客戶端向服務端發送
CertificateVerify
報文,其中包含了對通信雙方到目前爲止所有握手報文的數字簽名,用於證明自己擁有的私鑰與之前發送的證書中的公鑰相對應。可選,給服務端發送
Certificate
報文時發送 -
客戶端向服務端發送
ChangeCipherSpec
報文,表示從下條消息開始進行加密傳輸。 -
客戶端向服務端發送
Finished
報文,加密傳輸,其中包含了所有握手消息的數字摘要,用於防篡改。
第四次握手
-
服務端向客戶端發送
ChangeCipherSpec
報文,表示從下條消息開始進行加密傳輸。 -
服務端向客戶端發送
Finished
報文,加密傳輸,其中包含了所有握手消息的數字摘要,用於防篡改。
最後
SSL/TLS 協議也並非絕對安全,它也有許多漏洞被黑客們不斷地挖掘出來,當然,SSL/TLS 協議也在不斷地完善。2018 年發佈的 TLS 1.3 版本就在 TLS 1.2 版本的基礎上做了許多增強。比如,在性能上,握手階段從 2-RTT 縮減爲 1-RTT,並支持 0-RTT 模式;在安全上,ServerHello
報文之後就開始加密傳輸、一些不安全的加密套件也不再支持(比如靜態 RSA、Diffie-Hellman 等)。
雖然 TLS 1.3 版本機制上改變了很多,但是基本原理還是一樣的。因此,把 SSL/TLS 協議原理理解透了,後續不管版本再怎麼演進,我們都能快速完成協議機制的學習。
參考
The Transport Layer Security (TLS) Protocol Version 1.2,RFC 5246
The Transport Layer Security (TLS) Protocol Version 1.3,RFC 8446
SSL/TLS 協議運行機制的概述,阮一峯
Overview of SSL/TLS Encryption, MicroSoft Document
The First Few Milliseconds of an HTTPS Connection,Jeff Moser
爲什麼 HTTPS 需要 7 次握手以及 9 倍時延,面向信仰編程
HTTPS 權威指南,楊洋、李振宇等
數字證書, 百度百科
更多文章請關注微信公衆號:元閏子的邀請
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/Msyaf7Q2Ga5ZgTABRtOWGw