交流評論、關注點贊

  • Facebook Icon臉書專頁
  • telegram Icon翻牆交流電報群
  • telegram Icon電報頻道
  • RSS訂閱禁聞RSS/FEED訂閱

掃盲 HTTPS 和 SSL/TLS 協議[4]:歷史版本的演變及 Record 協議的細節

2018年09月05日 19:11 PDF版 分享轉發

來源:https://program-think.blogspot.com/2018/09/https-ssl-tls-4.html#1536082516085

文章目錄★名詞解釋
★SSL/TLS 歷史版本的演變及差異
★Record 協議概述
★Record 協議的結構
★各種類型 Record 簡介
俺一直在等 TLS 1.3 定稿(之所以這麼期待,因為 1.3 是一次【大】升級)。
前些天(2018年8月),IETF 終於發布了 RFC 8446,標志著 TLS 1.3 協議大功告成。於是俺就來繼續完成本系列的後面幾篇。
本系列的前一篇,咱們聊了”密鑰交換/密鑰協商”的相關演算法。從這篇開始,會逐步談及協議的細節,今天就從 Record 協議說起。由於恰逢 TLS 1.3 新鮮出爐,俺也順便聊聊 SSL/TLS 歷史上幾個版本的演變及差異。

★名詞解釋

對於本文會涉及到的幾個專業術語,先放上相應的解釋。

◇塊加密演算法

“塊加密演算法”又稱”分組加密演算法”,洋文叫做”Block Cipher”,相關的鏈接在”這裏”。
顧名思義,就是這類加密演算法要求:被加密的明文數據必須分成【相同大小】的若干坨(每一坨的大小稱為【塊長度】)。
以目前流行的對稱加密演算法 AES 為例。AES 的【塊長度】是”128 比特”(16位元組)。也就是說,AES 要求被加密的明文必須是【128位】的整數倍。
由於【塊加密演算法】對明文的長度有要求,所以用這類演算法對明文數據進行加密之前,要先進行【補齊】——在明文數據末尾追加一些垃圾數據,使之達到【塊長度】的整數倍。

◇流加密演算法

與”塊加密演算法”相對應的是”流加密演算法”,洋文叫做”Stream Cipher”,相關的維基百科頁面在”這裏”。
與”塊加密演算法”最大的差別在於——流加密演算法對明文數據的長度【沒有】要求(可以是任意位元組數)。
典型的流加密演算法是 RC4(順便提一句:RC4 裏面的 R 也就是 RSA 的那個 R)

◇MAC(消息認證碼)

MAC 是洋文”Message Authentication Code”的縮寫,維基百科的介紹在”這裏”。這玩意兒是通訊及密碼學的常見的概念——用 MAC 演算法來確保某個信息在傳輸的過程中【沒有】被篡改。
說到這兒,某些聰明的同學已經聯想到【散列函數】——用散列函數計算出來的哈希值確實可以用來作為 MAC。這種基於哈希(HASH)的”消息驗證代碼”也稱作”HMAC”。不了解哈希演算法的同學可以看這篇博文:《掃盲文件完整性校驗——關於散列值和數字簽名》

◇MAC 的幾種搞法

常見的有如下三種。俺從維基百科剽竊了對應的流程圖,大伙兒看圖就明白其原理,省得俺浪費力氣打字了。

Encrypt-then-MAC (EtM)

不見圖 請翻牆
先加密明文得到密文,再根據密文計算 MAC,最後把密文與 MAC 合併成一坨

Encrypt-and-MAC (E&M)

不見圖 請翻牆
對明文加密得到密文,對明文計算 MAC,最後把密文與 MAC 合併成一坨

MAC-then-Encrypt (MtE)

不見圖 請翻牆
對明文計算 MAC,把明文與 MAC 合併成一坨,然後一起加密

◇AE(帶認證的加密)

傳統的加密演算法只負責實現【保密性】,而不負責【完整性】。這麼說有點抽象,俺舉個例子:
假設你把一段明文 P 加密為一段密文 C,通過網路把 C 發送給另一個人。中途如果被攻擊者篡改了(把 C 修改為 C’),那麼接收方收到 C’ 之後,還是可以正常進行解密操作(當然,解密之後得到的就不再是 P 了,而是得到一段無意義的數據)
為了解決上述弊端,業界引入 AE(Authenticated Encryption)演算法的概念。也就是說,AE 演算法不但能做到【保密性】還可以做到【完整性】。
剛才掃盲的三種 MAC 實現方式,【從理論上講】就可以算 AE 啦。但上述那三種 MAC 的實現方式有個弊端——【解密】的一方還要自己進行 MAC 的驗證操作。這種搞法既麻煩又增加額外風險。比如說:寫解密代碼的程序猿萬一太粗心忘記進行驗證,豈不前功盡棄?

Ad:美好不容錯過,和家人朋友一起享受愉快時光,現在就訂票

◇【真正的】 AE

為了避免上述提到的弊端,密碼學界那幫專家又搗鼓出一些新的演算法(比如 CCM、GCM)。這些演算法可以在解密的同時驗證數據的有效性,而且這些演算法也【不】需要再額外存儲一個獨立的 MAC 數據。
本文後續部分提及的 AE,如果沒有特別說明,就是指這類【真正的】AE。
知名的那些 AE 演算法,可以組合現有的加密演算法。比如說:從 TLS 1.2 開始引入的 GCM 和 CCM,這兩個 AE 演算法都可以組合 AES128 與 AES256 加密演算法。
組合現有加密演算法的好處不光是避免重新發明輪子,而且還可以充分利用硬體加速。比如 AES 作為對稱加密的標準演算法,某些晶元(比如 Intel/AMD)會把 AES 演算法直接做成 CPU 指令,以實現硬體加速。

◇AEAD

AEAD 是洋文”Authenticated Encryption with Associated Data”的縮寫,普通話叫做”帶關聯數據的認證加密”。簡而言之,AEAD 是 AE 的變種。為了方便理解,俺再來找個栗子:
比如說在網路通訊中,數據包的【頭部】必須是明文且保證完整性;而數據包的【載荷】既要加密(保密性)又要保證完整性。這時候 AEAD 演算法就派上用場啦——數據包的【頭部】就是 AEAD 演算法裏面的【關聯數據】。

◇前向保密 / 完美正向加密

在本系列的前一篇《密鑰交換(密鑰協商)演算法及其原理》,俺已經補充了一個章節,簡單掃盲了一下”回溯性破解”與”前向保密”的概念。
所以這裏就不再浪費口水啦。

★SSL/TLS 歷史版本的演變及差異

趁著 TLS 1.3 正式發布的大好時機,簡單掃盲一下 SSL/TLS 各個版本的差異。

◇SSL 1.0

在本系列的第一篇,俺曾經提到:SSL 是上世紀90年代中期,由網景公司設計的。早期設計者是網景公司的 Taher Elgamal(一位埃及的密碼學家)。此人也被譽為”SSL 它爹”。
SSL 1.0 【從來沒有】正式發布過,所以業界對它了解不多。之所以沒有正式發布,據說是設計完之後發現了若干嚴重的安全缺陷,就不好意思再拿出來丟人現眼。

◇SSL 2.0

SSL 2.0 是 1995 年正式發布滴,坦率地說,協議設計比較粗糙。
比如俺在前一篇介紹過”密鑰交換演算法”和”身份認證演算法”。在這兩方面,SSL 2.0 都僅僅支持 RSA 這一種演算法。
另一個值得吐槽之處是:SSL 2.0【沒有】考慮到”前向保密”(洋文是”forward secrecy”),因此會遭遇【回溯性破解】的風險。(關於”前向保密”與”回溯性破解”,請看本文開頭的名詞解釋)

◇SSL 3.0

SSL 2.0 發布之後不久,又被發現若干安全漏洞。所以又趕緊在 1996 年發布了 SSL 3.0 版本。(接連兩個版本都不太靈光,看來”SSL 它爹”的水平實在令人不敢恭維)
這個 3.0 版本可以說是另起爐灶——換了幾個密碼學專家,【重新設計】了 SSL 協議。所以 SSL 3.0 相比 SSL 2.0 有很大差別。
關於 SSL 3.0 的權威技術規範,可以參見 RFC 6101

請允許俺稍微跑題一下:
重新設計 SSL 3.0 的那些專家,為首的是來自斯坦福大學的 Paul Kocher——此人堪稱密碼學奇才,SSL 3.0 發布的那年(1996),他才23歲(回想俺23歲的時候,在密碼學方面是只菜鳥,真是情何以堪)。
在同一年,他還發表了篇論文,描述了一種【全新的】密碼學攻擊方式——timing attack(基於時間因素的邊通道攻擊)。這種攻擊手法的原理,說起來並不算複雜,但很有創意,之前從來沒人想到過。

◇TLS 1.0

TLS 1.0 是 1999 年發布滴,技術規範參見 RFC 2246。
為啥從 SSL 改名為 TLS 捏?主要是安全性在 Web 世界中越來越重要,因此 IETF組織急需把 SSL 的協議【標準化】,為了以示區別,另外起個名字叫 TLS(洋文”Transport Layer Security”的縮寫)。
雖然協議名改了,但其實 TLS 1.0 與 SSL 3.0 的差別不大。這點從協議版本號也可以看出來——TLS 1.0 內部的協議版本號其實是【3.1】。

◇TLS 1.1

TLS 1.1 是 2006 年發布滴,技術規範是 RFC 4346。
發布該版本的主要動機是:修補 CBC(cipher-block chaining)相關的漏洞,以防範某些攻擊(比如”padding oracle attack”)。
在 1.1 版本,原有的”【隱式】初始化向量”改為”【顯式】初始化向量”,修正了 CBC 方式下填充數據的缺陷。

◇TLS 1.2

TLS 1.2 是 2008 年發布滴,技術規範是 RFC 5246。
相比 TLS 1.1 的變化如下:

支持 AEAD 加密模式(參見 RFC 5116)
加密演算法廢棄了 DES、DES40、IDEA、RC2
HMAC 增加了 SHA256

◇TLS 1.3

俺寫本文時,TLS 1.3 剛剛新鮮出爐沒幾天(2018年8月),其技術規範是 RFC 8446。
所謂的”十年磨一劍”,這個 1.3 版本是一次雄心勃勃的升級,相對 TLS 1.2 加了不少東西,也刪了不少東西。考慮到篇幅,俺挑幾個主要的來說說:

首先要表揚的是:TLS 1.3 完善了 SNI(Server Name Identification)擴展,非常有利於翻牆工具藉助【依附的自由】對抗網路封鎖;
其次是強制使用”完美正向加密(PFS)”,所以很多做不到 PFS 的密鑰協商演算法在 TLS 1.3 規範中被無情地拋棄了(比如:RSA、靜態 DH、靜態 ECDH…);
傳統的 HMAC 也被無情地拋棄了,今後只使用 AEAD 方式來保障完整性(關於 AEAD,請看本文開頭的名詞解釋);
原有的對稱加密演算法只保留 AES(3DES、RC4 廢棄),另增加 CHACHA20 流加密演算法;
壓縮特性被廢除(以消除 CRIME 攻擊的風險);
初始握手的過程有大的改變(這個等下一篇再聊)
…..

★Record 協議概述

很多介紹 SSL/TLS 的文章都把 record 協議給忽略了。可能這些文章的作者覺得 record 協議不太重要。但俺出於負責任的心態,覺得還是有必要跟大伙兒聊一下。
SSL/TLS 協議在通訊的過程中會把需要傳輸的數據分成一坨一坨的,每次都只發送或接收一坨。在洋文中,每一坨稱為一個 record。下面要聊的”Record 協議”,就是用來定義這個 record 的格式。

★Record 協議的結構

Record 協議比較簡單,主要結構見下表:

欄位名稱欄位長度備註類型1位元組版本2位元組TLS 1.3 廢棄,僅留作向下兼容載荷長度2位元組消息0~N 位元組消息認證碼0~N 位元組TLS 1.3 不需要該欄位填充0~N 位元組

◇類型(type)

“類型”欄位是個枚舉值,協議允許的有效值如下:

十進位十六進位含義備註0x1420ChangeCipherSpec(切換到加密方式)TLS 1.3 廢棄0x1521Alert(告警)0x1622Handshake(握手)0x1723Application(應用層數據)0x1824Heartbeat(心跳)始於 TLS 1.3
  (關於表格中每一種類型,下面會有詳細介紹)

◇版本(version)

“版本”欄位含兩個位元組,分別表示:主版本號 和 次版本號。有效值如下:

主版本號次版本號含義0x20x0SSL 2.00x30x0SSL 3.00x30x1TLS 1.00x30x2TLS 1.10x30x3TLS 1.2
  注:從 TLS 1.3 版本開始,”版本”欄位已經被廢棄,僅用於向後兼容。

◇長度(length)

“長度”欄位含兩個位元組,表示載荷長度。
對於【明文】的 record,【沒有】”消息認證碼”欄位,也【沒有】”填充”欄位——”載荷長度”也就是消息的長度。
對於【加密】的 record——”載荷長度”是”消息、消息驗證碼、填充”三者的長度之和。
SSL/TLS 協議規定了長度欄位最多只能表示 0~16384 位元組(214 = 16384)。

◇消息(message)

每個 record 的”消息”欄位的內容取決於”類型”欄位。關於這個”消息”欄位,待會兒再聊。

◇消息認證碼(MAC)

關於 MAC 這個概念,參見本文開頭部分的名詞解釋,此處不再浪費口水。
在 SSL/TLS 協議中,MAC 對於明文的 record 沒有意義(為啥沒意義,請自行思考)。
對於【加密】的 record,要分兩種情況:
其一,如果是【傳統的】塊加密與流加密,會帶有額外的 MAC;
其二,如果使用 AEAD 加密模式,其本身已經內置了【完整性】的校驗,不需額外的 MAC。
前面提到,AEAD 是從 TLS 1.2 開始引入,到了 TLS 1.3 就【只支持】AEAD 啦。所以 TLS 1.3 【沒有】MAC 部分。
SSL/TLS 各個版本實現【完整性】的方式:

演算法SSL 2.0SSL 3.0TLS 1.0TLS 1.1TLS 1.2TLS 1.3HMAC-MD5是是是是是否HMAC-SHA1否是是是是否HMAC-SHA256否否否否是否AEAD否否否否是是

◇填充(padding)

只有當 record 是加密的,並且使用的加密演算法屬於【塊加密演算法】,才會使用”填充”欄位。

★各種類型 Record 簡介

從 Record 協議的頭部類型欄位可以看出,總共有5種類型的 Record。下面簡單說一下:

◇握手(Handshake)

Record 協議的”類型”欄位為 22(0x16),表示這條 record 是 Handshake 類型。
“握手”的意思就是——通訊雙方初次打交道,需要交換一些初始化的信息。
對於 SSL/TLS 協議,為了建立起【可靠的】加密通道,通訊雙方需要在握手的過程交換很多信息(加密演算法、壓縮演算法、MAC 演算法、等等)。所以這個握手的過程是比較複雜滴,需要耗費很多口水。俺留到本系列的下一篇,專門來聊”握手的細節”。
由於握手的過程,加密通道尚未建立,所以用來進行握手的 record 是【明文】滴,並且也【沒有】”MAC”欄位及”填充”欄位。

◇切換到加密方式(ChangeCipherSpec)

Record 協議的”類型”欄位為 20(0x14),表示這條 record 是 ChangeCipherSpec 類型。
這個 ChangeCipherSpec 也是跟握手過程相關滴,留到下一篇。
注:從 TLS 1.3 版本開始,ChangeCipherSpec 類型的 record 已經被廢棄,僅用於向後兼容。

◇應用層數據(Application)

Record 協議的”類型”欄位為 23(0x17),表示這條 record 是 Application 類型。
也就是說,這條 record 的載荷部分存放的是上層(應用層)協議的數據。既然傳輸的是上層數據,肯定得是【加密】滴!但不一定有”MAC”欄位。要看具體的 SSL/TLS 版本(如下):
1. 對於 TLS 1.1 及之前的版本,總是使用 HMAC 進行完整性校驗,所以總是含有”MAC”欄位。
2. 對於 TLS 1.2,如果握手之後採用 AEAD 加密模式,就沒有 MAC;反之,則有 MAC。
3. 對於 TLS 1.3 及之後的版本,只支持 AEAD,【不】再有”MAC”欄位。
另外,在 TLS 1.2 及【之前】的版本中,還支持”對應用層數據進行壓縮”。本來俺還想聊聊這方面的實現細節。但是 TLS 1.3 已經【廢棄】了壓縮選項(為了防 CRIME 攻擊),恐怕未來版本也不會再有壓縮選項了。搞得俺也沒積極性來聊這個話題了 🙁

◇告警(Alert)

Record 協議的”類型”欄位為 21(0x15),表示這條 record 是 Alert 類型。
這種類型的 record 用來發送警告或出錯信息。
在通訊的過程(包括握手過程)中,有時候某一方會發現不對勁(比如收到的數據出現缺失或錯誤),這時候就要發送一條 Alert 類型的 record 給對方。
不對勁的情況分為兩種,洋文分別稱之為 Warning 和 Fatal。兩者的差別在於:

Warning 表示通訊出現【不穩定】的情況(這種”不穩定”通常是【可恢復】滴)
Fatal 表示通訊出現【不可靠】的情況(比如:證書失效、數據被篡改。這種”不可靠”通常是【不可恢復】滴)

如果不對勁的情況屬於 Warning,通訊可能會繼續也可能會斷開;如果不對勁的情況屬於 Fatal,通訊會在發送 Alert 之後立即斷開。
這種類型的 record,其”消息”欄位僅有2位元組,頭一個位元組表示告警的”級別/Level”(1表示 warning,2表示 fatal);后一個位元組表示具體的描述(有一個對照表,用不同的整數表示不同的情況)。
如果在握手【之後】發送告警,此時雙方已經建立起加密通道,則告警 record 的”消息”欄位是【密文】的。
如果在握手【之前】發送告警,此書尚未建立加密通道,則告警 record 的”消息”欄位是【明文】的。

◇心跳(Heartbeat)

Record 協議的”類型”欄位為 24(0x18),表示這條 record 是 Heartbeat 類型。
這種類型的 record 用來發送心跳信息。
所謂的【心跳】,主要用來確認”通訊的對端依然正常”。在 SSL/TLS 連接建立之後,有可能在某些情況下出現【通訊空閑】(上層的協議在某個時間段沒有數據傳輸)。這時候就需要依靠【心跳機制】來判斷對方是否還活著。
由於”心跳”的傳輸是在加密通道建立之後,所以”心跳”的 record 是加密的。
關於這個心跳機制的技術細節,請參見 RFC6520(鏈接在”這裏”)。
這個心跳協議的 RFC 發佈於2012年(晚於2008年的 TLS 1.2),因此目前只有 TLS 1.3 版本才支持它。

搬瓦工翻牆 Just My Socks

推薦安卓翻牆APP:SpeedUp VPN

Android版SpeedUp VPN,基於ShadowsocksRb,與SSR和Shadowsocks協議兼容,內置免費SSR伺服器。 如果您對內置SSR VPN伺服器不滿意,則可以自行添加或導入任何SSR和Shadowsocks伺服器使用。

喜歡、支持,請轉發分享↓Follow Us 責任編輯:劉鈺