更好的 TLS 1.3 協(xié)議解析

網(wǎng)絡(luò)安全篇,面對(duì)復(fù)雜多變的網(wǎng)絡(luò)環(huán)境,我們需要掌握哪些關(guān)于網(wǎng)絡(luò)安全的相關(guān)知識(shí),聊一聊與網(wǎng)絡(luò)安全相關(guān)的:HTTPS、SSL、TLS 等。


網(wǎng)絡(luò)安全專題
  • 網(wǎng)絡(luò)安全的基石

網(wǎng)絡(luò)安全 — HTTPS
網(wǎng)絡(luò)安全的基石(上)— 加密
網(wǎng)絡(luò)安全的基石(下)— 完整性與身份認(rèn)證
公鑰信任問題 — 數(shù)字證書與 CA
信任始于握手 — TLS 連接過程詳解

  • HTTPS 的優(yōu)化

《TLS 1.3 特性解析》
如何優(yōu)化 HTTPS 連接》- 待完善


早在 2013 年,IETF(互聯(lián)網(wǎng)工程小組) 就對(duì) TLS 1.2 的過時(shí)設(shè)計(jì)和兩次往返開銷心生不滿,因此開始著手準(zhǔn)備新版本的 TLS。同年 8 月由 Eirc Rescorla 提議出新版本 TLS 的功能愿望清單。在經(jīng)過一番辯論后,最終該提議內(nèi)容被定義為 TLS 1.3。推動(dòng) TLS 1.3 設(shè)計(jì)的主要問題大概有:

  • 減少握手延遲
  • 加密更多的握手
  • 提高抵御跨協(xié)議攻擊的彈性
  • 刪除舊功能

終于在 2018 年 8 月 10 日,歷經(jīng) 4 年時(shí)間,TLS 1.3 最終版本發(fā)布了 — RFC-8446。新的協(xié)議使得互聯(lián)網(wǎng)變得更快、更安全;隨著 TLS 1.3 的采用率不斷提高,它勢(shì)必會(huì)長(zhǎng)遠(yuǎn)影響互聯(lián)網(wǎng)的發(fā)展;同時(shí)盡快將 TLS 1.3 平滑應(yīng)用到線上環(huán)境無疑是勢(shì)在必行。

不過在這之前, TLS 1.2 的應(yīng)用也已經(jīng)有 10 年(2008 年)的時(shí)間了,畢竟歷經(jīng)了種種考驗(yàn),新的協(xié)議在推廣和部署上必定會(huì)帶來新的挑戰(zhàn)。接下來我們就來看看新版本的 TLS 是如何做的?

“歲月不饒人”,如今互聯(lián)網(wǎng)的發(fā)展已使 TLS 1.2 在安全、性能等方面不能滿足如今的需求。


兼容性

由于 TLS 1.1/1.2 等協(xié)議已經(jīng)出現(xiàn)了很多年,很多應(yīng)用軟件、中間代理(Middlebox)只認(rèn)老的記錄協(xié)議格式,更新改造很困難,甚至僵化。

可部署性

正式由于這些中間代理/軟件(Middlebox)在新的更改中表現(xiàn)不佳,即使是對(duì) TLS 1.3 協(xié)議的細(xì)微更改(例如消除冗余的 ChangeCipherSpec 消息,版本號(hào)從 0x03 升級(jí)為 0x04),也最終導(dǎo)致了某些設(shè)備的連接失敗問題。這也是 TLS 1.3 從草稿到最終發(fā)布花費(fèi)了這么長(zhǎng)時(shí)間的重要原因之一。

為了保證這些被廣泛部署的“舊設(shè)備”能夠繼續(xù)使用,TLS 1.3 不得不做出妥協(xié),通過“偽裝”來實(shí)現(xiàn)兼容:保持現(xiàn)有的記錄格式不變,使得 TLS 1.3 看上去“像是” TLS 1.2。

擴(kuò)展協(xié)議

那么,如何區(qū)分是 1.2 還是 1.3 呢?

這里用到一個(gè)新的擴(kuò)展協(xié)議(Extension Protocol),它有點(diǎn)“補(bǔ)充條款”的意思,通過在記錄末尾添加一系列的“擴(kuò)展字段”來增加新的功能,舊版本的 TLS 不認(rèn)識(shí)它可以直接忽略,這就實(shí)現(xiàn)了“向后兼容”。

在記錄頭的 Version 字段被兼容性“固定”的情況下,只要是 TLS 1.3 協(xié)議,握手的 “Hello” 消息后面就必須有 “supported_versions” 擴(kuò)展,它標(biāo)記了 TLS 的版本號(hào),使用它就能區(qū)分新舊協(xié)議。

Handshake Protocol: Client Hello
    Version: TLS 1.2 (0x0303)
    Extension: Supported_versions (len=11)
        Supported Version: TLS 1.3 (0x304)
        Supported Version: TLS 1.2 (0x0303)

TLS 1.3 正是利用擴(kuò)展實(shí)現(xiàn)了許多重要的功能,比如 “supported_groups” “key_share” “signature_algorithms” “server_name” 等。


強(qiáng)化安全

在經(jīng)歷十余年的實(shí)踐中獲得許多寶貴經(jīng)驗(yàn)的 TLS 1.2 陸續(xù)發(fā)現(xiàn)了很多的漏洞和加密算法的弱點(diǎn)。因此消除潛在的危險(xiǎn)設(shè)計(jì)來糾正以前的錯(cuò)誤成為 TLS 1.3 的設(shè)計(jì)目標(biāo)之一。所以新版本的 TLS 協(xié)議里要修補(bǔ)這些不安全的因素。

例如:

  • 偽隨機(jī)函數(shù)由 PRF 升級(jí)為 HKDF(HMAC-based Extract-and-Expand Key Derivation Function);
  • 明確禁止在記錄協(xié)議里使用壓縮;
  • 廢除了 RC4、DES 對(duì)稱加密算法;
  • 廢除了 ECB、CBC 等傳統(tǒng)分組模式;
  • 廢除了 MD5、SHA1、SHA-244 摘要算法;
  • 廢除了 RSA、DH 密鑰交換算法和許多命名曲線。

固定密鑰交換

經(jīng)過這樣一番“減肥瘦身”之后,TLS 1.3 的密鑰交換算法只有 ECDHE 和 DHE 了,關(guān)于橢圓曲線(ECC)也被“砍”到只剩 P-256 和 x25519 等 5 種。

首先來說下廢除 RSA 和 DH 密鑰交換算法的原因:

由于客戶端默認(rèn)會(huì)選擇 ECDHE 而非 RSA 做密鑰交換,這是因?yàn)樗痪哂小?strong>前向安全”(Forward Secrecy):“假設(shè)有人長(zhǎng)期記錄了加密的數(shù)據(jù),然后在后續(xù)的某個(gè)時(shí)間段獲得了服務(wù)器的 RSA 私鑰,那么黑客就能夠使用該私鑰解密出之前所有報(bào)文的 “Pre-Master”,再計(jì)算出會(huì)話密鑰,破解所有密文。這便是今日截獲,明日破解

而 ECDHE 算法在每次握手時(shí)都會(huì)生成一對(duì)臨時(shí)公鑰和私鑰,每次通信的秘鑰對(duì)都是不同的,也就是“一次一密”,即使黑客花大力氣破解了這一次的會(huì)話密鑰,也只是這次通信被攻擊,之前的歷史消息不會(huì)受到影響,仍然是安全的。

所以現(xiàn)在主流的服務(wù)器和客戶端在握手階段都已經(jīng)不再使用 RSA,改用 ECDHE,而 TLS 1.3 在協(xié)議里明確廢除了 RSA 和 DH 則在標(biāo)準(zhǔn)層面保證了“前向安全”。

暫時(shí)性 DH 成為在 TLS 1.3 中唯一的密鑰交換機(jī)制。

固定密碼

多年以來,密鑰交換機(jī)制不是唯一引起安全漏洞的部分,對(duì)稱密鑰部分也有相當(dāng)一部分問題。

同樣,用于對(duì)稱加密的算法在經(jīng)過“減肥瘦身”之后也只保留了 AES、ChaCha20 ,分組模式只能用 AEAD 的 GCM、CCM 和 Poly1305,摘要算法也只能用 SHA 256、SHA 384。

這樣原來眾多的加密算法、參數(shù)組合導(dǎo)致密碼套件非常復(fù)雜,難以選擇。而經(jīng)過瘦身之后的 TLS 1.3 只剩下 5 個(gè)套件,使得客戶端或服務(wù)端在選擇密碼套件時(shí)變得“更加容易”。然而更重要的是,這些算法在 TLS 長(zhǎng)期的實(shí)踐過程中先后已經(jīng)被證實(shí)是構(gòu)成不安全的因素,從而導(dǎo)致安全漏洞。

修復(fù)數(shù)字簽名

經(jīng)過前面的學(xué)習(xí),相信你也知道 TLS 另一個(gè)重要部分是身份驗(yàn)證。在每個(gè)連接中服務(wù)都是用具有公鑰的數(shù)字證書向客戶端提供身份認(rèn)證。在 RSA 加密模式下,服務(wù)器通過解密預(yù)主密鑰并通過對(duì)話記錄計(jì)算 MAC 來證明其對(duì)私鑰的所有權(quán)。在 Diffie-Hellman 模式下,服務(wù)器使用數(shù)字簽名來證明私鑰的所有權(quán)。

在 TLS 1.2 和更早的版本中,服務(wù)器的簽名僅涵蓋部分握手。用于協(xié)商使用哪種對(duì)稱密碼的部分沒有由私鑰簽名。這也導(dǎo)致許多引人注目的漏洞 FREAKLogJam 等。而在 TLS 1.3 由于服務(wù)器對(duì)整個(gè)握手記錄進(jìn)行簽名,因此可以避免這些情況。


提升性能

HTTPS 建立連接時(shí)除了要做 TCP 握手,還要做 TLS 握手,在 TLS 1.2 中會(huì)多花兩個(gè)消息往返(2 - RTT),這可能導(dǎo)致幾十毫秒甚至上百毫秒的延遲,在移動(dòng)網(wǎng)絡(luò)中延遲還會(huì)更嚴(yán)重。

1-RTT 模式

密碼套件的大幅度簡(jiǎn)化,也就沒有必要再像以前那樣走復(fù)雜的的協(xié)商流程了。TLS 1.3 壓縮了以前的 “Hello” 協(xié)商過程,刪除了 “Key Exchange” 消息,把握手時(shí)間減少到了 “1-RTT”,效率提高了一倍。

下面是 TLS 1.3 握手過程的簡(jiǎn)圖,注意與前面介紹的 TLS 1.2 對(duì)比區(qū)別在哪里。

0-RTT 恢復(fù)

除了標(biāo)準(zhǔn)的 “1-RTT” 握手,受 QUIC 協(xié)議的啟發(fā),客戶端可以在其第一條消息中將加密的數(shù)據(jù)發(fā)送到服務(wù)器,與未加密的 HTTP 相比,沒有額外的延遲成本。

在 TLS 1.2 中,有兩種恢復(fù)連接的方法:會(huì)話 ID 和會(huì)話 Ticket,而 1.3 則將他們組合在一起形成稱為 PSK(pre-shared key,預(yù)共享密鑰)恢復(fù)的新模式。

握手分析

目前 Nginx 等 Web 服務(wù)器都能夠很好的支持 TLS 1.3,但是要求底層的 OpenSSL 必須是 1.1.1。因此如果要部署需要先升級(jí)你的 OpenSSL 版本。

首先TCP 建立連接之后,瀏覽器首先還是發(fā)一個(gè) “Client Hello”。

由于 1.3 的消息要兼容 1.2,所以開頭的版本號(hào)、支持的密碼套件和隨機(jī)數(shù)(Client Random)結(jié)構(gòu)都是一樣的(這時(shí)的隨機(jī)數(shù)是 32 個(gè)字節(jié))。

Handshake Protocol: Client Hello
    Version: TLS 1.2 (0x0303)
    Random: cebeb6c05403654d66c23290...
    Cipher Suites (18 suites)
        Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
        Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
        Cipher Suite: TLS_AES_256_GCM_SHA384 (0X1302)
    Extension: supported_versions (len=9)
        Supported Version: TLS 1.3 (0x0304)
        Supported Version: TLS 1.2 (0x0303)
    Extension: supported_groups (len=14)
        Supported Groups (6 groups)
            Supported Group: x25519 (0x001d)
            Supported Group: secp256r1 (0x0017)
    Extension: key_share (len=107)
        Key Share extension
            Client Key Share Length: 105
            Key Share Entry: Group: x25519
            Key Share Entry: Group: seco256r1

注意 “Client Hello” 里的擴(kuò)展,“supported_versions” 表示這是 TLS 1.3,“supported_groups” 是支持的曲線,“key_share”是曲線對(duì)應(yīng)的參數(shù)。

這有點(diǎn)是像是“有話盡量一口氣說完”,還是按照老規(guī)矩進(jìn)行“打招呼”,我這邊有這些信息,考慮到版本升級(jí),所以附帶了一些信息,可能后面會(huì)用到。

服務(wù)器收到 “Client Hello” 同樣返回 “Server Hello” 消息,還是要給出一個(gè)隨機(jī)數(shù)(Server Random)和選定密碼套件。

Handshake Protocol: Server Hello
    Version: TLS 1.2 (0x0303)
    Random: 12d2bce568bodedi3ee9...
    Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
    Extension: supported_versions (len=2)
        Supported Version: TLS 1.3 (0X0304)
    Extension: key_share (len=36)
        Key Share extension
            Key Share Entry: Group: 0x25519, Key Exchange length: 32

表面上看 Version 和 TLS 1.2 是一樣的,重點(diǎn)是后面的擴(kuò)展。“supported_versions” 里確認(rèn)使用的是 TLS 1.3,然后在 “key_share” 擴(kuò)展帶上曲線和對(duì)應(yīng)的公鑰參數(shù)。

服務(wù)器的回應(yīng)還是老套路,服務(wù)端對(duì)客戶端的提供的信息作出選擇,另外服務(wù)端還要再附加上幾個(gè)參數(shù),這次加密就協(xié)商定了。

可以看到相比 TLS 1.2 的握手過程,TLS 1.3 僅用兩條消息就共享了 4 個(gè)信息:Client RandomServer RandomClient ParamsServer Params。兩邊就可以各自用 DH 算出 “Pre-Master”,再用 HKDF 生成主密鑰 “Master Secret”,效率比 TLS 1.2 提高了一大截。

在計(jì)算出主密鑰后,服務(wù)器立刻發(fā)出 “Change Cipher Spec” 消息,比 TLS 1.2 提早進(jìn)入加密通信,后面的證書等就都是加密的了,減少握手時(shí)明文信息泄露。

TLS 1.3 還多了一個(gè) “Change Cipher Spec” 消息,服務(wù)器用私鑰把前面的曲線、套件、參數(shù)等握手?jǐn)?shù)據(jù)加了簽名,作用和 “Finished” 消息差不多。但由于是私鑰簽名,所以強(qiáng)化了身份認(rèn)證和防篡改。

兩個(gè)“打招呼”消息之后,客戶端驗(yàn)證服務(wù)器證書,再發(fā) “Finished” 消息,就正式完成了握手,開始收發(fā) HTTP 報(bào)文。

現(xiàn)在已經(jīng)有很多網(wǎng)站都支持了 TLS 1.3,例如 GitHub


最后

今天我們主要介紹了 TLS 1.3 的一些新特性,簡(jiǎn)單總結(jié)下來主要包含下面幾點(diǎn):

  1. 為了兼容舊的版本協(xié)議,TLS 1.3 不得不偽裝成 TLS 1.2 的外表,將新特性在“擴(kuò)展”中實(shí)現(xiàn);
  2. TLS 在之前的實(shí)踐應(yīng)用中,陸續(xù)發(fā)現(xiàn)了很多安全隱患,因此消除這些危險(xiǎn)因素成了 TLS 1.3 的設(shè)計(jì)目標(biāo)之一,其中包含大幅刪減了一些已經(jīng)被證實(shí)存在安全隱患的加密算法,從協(xié)議層面進(jìn)一步強(qiáng)化了安全。
  3. TLS 1.3 還簡(jiǎn)化了握手過程,只需要一個(gè)消息往返便可實(shí)現(xiàn)完全握手。

TLS 1.3 涉及的內(nèi)容很多,有關(guān)它的更詳細(xì)信息請(qǐng)去參照 RFC-8446,關(guān)于這部分大家還有哪些要分享的呢?歡迎您的留言或指正。


網(wǎng)絡(luò)安全系列專題

擴(kuò)展閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。