- 解析QUIC/HTTP3:未來互聯網的基石
- 劉準 陳保軍編著
- 5011字
- 2024-10-14 16:39:22
1.2 TLS版本演化
1.2.1 SSL系列協議
隨著互聯網越來越普及,網絡通信的環境也越來越復雜,網絡上的應用越來越容易受到攻擊。攻擊者可分為兩類:僅可以觀察到網絡上數據包的被動攻擊者和可以修改和注入數據包的主動攻擊者。因此,網絡通信的安全需要達到三個目標:保密性、消息完整性和端點認證。保密性指的是消息要進行加密,不能讓被動攻擊者觀察到消息的內容;消息完整性指的是如果主動攻擊者修改了消息的內容,接收者需要能夠檢測到這種修改;端點認證指的是確保通信的對端是正確的端點,而不是冒充的。
1994年4月,網景公司發布了SSLv2(Secure Socket Layer,安全套接層),意在為Web應用(主要是基于HTTP的應用)提供安全通信保障。由于SSL的設計簡單,對應用來講相對透明,再加上當時網景瀏覽器的市場占有率很高,SSLv2獲得了廣泛的認同和使用。
但由于SSLv2的設計和開發投入太少,也沒有安全專家的參與,所以安全性不高,很容易攻破。于是網景公司又請多位安全專家開始設計SSLv3,并于1995年末發布。SSLv3設計了新的規格描述語言,使用了新的記錄類型和數據編碼,增加了只認證不加密的模式,重寫了密鑰擴展算法,支持防止對數據流進行截斷攻擊的關閉握手。另外,網景公司還增加了多種新的加密算法:DSS(Digital Signature Standard,數字簽名標準)、Diffie-Hellman(DH)以及美國政府鼓勵的FORTEZZA加密套件。
SSLv3協議的具體描述可以參考RFC 6101,分為兩個階段:握手階段和數據傳輸階段。握手階段完成對端點的認證和確定保護數據傳輸的密鑰。一旦確定了密鑰,后面的數據傳輸和SSL協議過程都受到加密和完整性保護。SSLv3是一種分層協議,通過記錄層承載不同的消息類型來區分不同的內容;記錄層則由某種保證可靠性的協議承載,通常是TCP。SSLv3的分層如圖1-12所示。

圖1-12 SSLv3分層
SSLv3握手階段對預主密鑰進行協商,然后使用客戶端和服務器的隨機數擴展出不同的密鑰。
首先使用PRF(Pseudo Random Function,偽隨機函數)從協商出的預主密鑰、客戶端隨機數和服務器隨機數擴展出主密鑰。PRF的定義為:


主密鑰計算方法可以簡單表示為:

然后使用偽隨機函數從主密鑰、客戶端隨機數和服務器隨機數、衍生標簽擴展出不同用途的密鑰:

各密鑰間的關系可以簡化為圖1-13,其中IV指初始向量。

圖1-13 SSL密鑰導出示意圖
圖1-14展示了SSL典型的首次握手過程。
1)客戶端先發出ClientHello消息,其中包含了支持的加密算法和隨機數,可能還有壓縮算法,但很少使用。隨機數用于產生最終的主密鑰(通常也稱為master_secret),用于保證不同連接在預主密鑰(通常也稱為pre_master_secret)相同的情況下仍然可以產生不同的主密鑰,保證主密鑰的前向安全,也用于保證其他信息都相同情況下握手信息的消息認證碼不同,以用于抗重放攻擊。
2)服務器回復ServerHello消息,其中包括從ClientHello消息中選中的加密算法和隨機數。同時通過Certificate消息發送服務器證書,其中包含服務器的公鑰。然后發送ServerHelloDone消息,這個消息中沒有實際內容,只是為了兼容其他變種中服務器還需要發送其他消息的場景。

圖1-14 SSL典型的首次握手過程
注意 示例中服務器沒有要求客戶端提供證書,這是大多數的應用場景;但有的場景下服務器是需要認證客戶端的,這種情況下客戶端需要提供證書。
3)客戶端驗證服務器證書后,生成加密預主密鑰,使用服務器證書的公鑰加密后,在ClientKeyExchange消息中發送給服務器。需要說明的是,示例中使用的是RSA(RSA加密算法)交換預主密鑰,如果使用DH算法交換預主密鑰,服務器也需要發送一個ServerKeyExchange消息;使用臨時RSA也需要ServerKeyExchange消息發送加密預主密鑰的臨時公鑰。
4)客戶端發送ChangeCipherSpec消息,表示后續消息使用協商好的主密鑰加密;然后發送加密的Finished消息,其中包含握手信息的消息認證碼。
5)服務器收到預主密鑰(或者使用DH算法時計算出預主密鑰),發送ChangeCipherSpec消息,表示后續消息使用協商好的主密鑰加密;然后發送加密的Finished消息,其中包含握手過程中所有消息的散列值(verify_data字段)。
由于證書校驗和密碼協商是比較消耗CPU的工作,也增加了連接建立的RTT(Round-Trip Time,往返時延),根據《SSL與TLS》一書中的數據,使用512位RSA時,恢復連接比重建連接握手性能提高了20倍。所以SSL還設計了恢復連接的簡單方法,其典型過程如圖1-15所示。首次連接時,如果服務器想要支持后續的連接恢復,可以在ServerHello消息中攜帶sessionID;客戶端收到后存儲服務器的sessionID和本次產生或計算的預主密鑰;下次發起連接時在ClientHello消息中將sessionID帶給服務器;服務器如果選擇恢復sessionID對應的預主密鑰,則將相同的sessionID在ServerHello中返回給客戶端,然后直接計算出主密鑰,發送ChangeCipherSpec消息和Finished消息。

圖1-15 SSL恢復連接的典型過程
這種方法也可用于使用同一個預主密鑰快速建立多個連接,這時隨機數的作用就凸顯了出來,不同的隨機數可以為多個連接建立不同的主密鑰,從而得到了連接間的安全隔離。
注意 SSLv3于2015年廢棄(見RFC 7568),但基本框架和協議過程還存在于TLS的實現中。
1.2.2 TLS 1.0
1996年5月,IETF組建TLS工作組來標準化傳輸層安全協議,主要基于SSLv3。由于微軟與網景為Web統治權爭斗地非常激烈,再加上PKIX(Public Key Infrastructure,公用密鑰信息基礎設施)工作組陷入停頓,經過漫長的過程,TLS 1.0最終于1999年1月發布為RFC 2246。TLS 1.0可以看作SSLv3的標準化版本,因此也被認為是SSLv3.1,這從版本號也可以看出來,TLS 1.0版本號為0x0301,而SSLv3版本號為0x0300。但TLS 1.0相對于SSLv3也有一些小的改進:定義了基于標準HMAC的PRF(將HMAC-MD5和HMAC-SHA異或),消息認證碼使用了標準的HMAC(Hash-based Message Authentication Code,基于散列的消息驗證碼),補充了一些告警碼,改進了證書鏈的大小(SSL需要完整的證書鏈,而TLS 1.0只需要到信任的CA),去除了FORTEZZA的支持,規定了必須支持DH、DSS和3DES,將TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA作為唯一強制支持的加密套件。這是因為IETF傾向于使用免費的、經過詳細論證、安全的算法(RSA當時還在專利保護期內,于2000年9月過期,DSS則沒有這種問題,FORTEZZA則不夠透明、沒有經過安全性的詳細論證)。雖然TLS 1.0和SSLv3非常相似,但不能互操作。
TLS 1.0的基本原理和協議過程跟SSL3.0并沒有差別,這里就不重復介紹了。TLS 1.0中密鑰衍生的方法并沒有變化,但PRF的計算方法改變為:

其中seed使用兩端的隨機數之和;S1、S2分別是secret的前一半和后一半,如果secret是奇數個字節,S1最后一個字節和S2第一個字節相同;P_MD5和P_SHA-1計算方法為:

主密鑰計算方法仍然簡單表示為:

然后使用偽隨機函數從主密鑰、客戶端隨機數和服務器隨機數、衍生標簽擴展出不同用途的密鑰:

但是后來發現TLS 1.0有一些安全問題,這在之后的TLS 1.1中得以解決。首先是CBC(Cipher Block Chaining,密文分組鏈接)模式下IV(Initialization Vector,初始化向量)除了第一個記錄來自于計算得到的值,之后其他記錄的IV來自于上一個記錄的最后一個密文塊。CBC加密和解密模式原理分別如圖1-16和圖1-17所示。2011年披露的BEAST攻擊就是利用了這個特性。TLS 1.0得到IV的方式使得主動攻擊者可以觀察到當前記錄的IV,然后猜測一個數據塊,將其與IV和前一個密文塊進行異或操作,并將得到的數據塊注入會話,這樣可以檢查猜測的數據塊是否正確。

圖1-16 CBC加密示意圖

圖1-17 CBC解密示意圖
1.2.3 TLS 1.1
2006年4月,TLS 1.1發布為RFC 4346,修復了一些關鍵的安全問題,包括:CBC加密使用每條記錄一個的顯式IV;為了防止CBC填充攻擊,使用bad_record_mac錯誤碼代替decryption_failed回復填充錯誤;支持傳輸參數的IANA(Internet Assigned Numbers Authority,互聯網數字分配機構)注冊,增加了傳輸參數的靈活性;改進了連接關閉過早情況下的連接恢復問題。
IETF從2021年3月25日起廢棄了TLS 1.0和TLS 1.1,見RFC 8996,原因是TLS 1.0和TLS 1.1存在一些安全漏洞,還存在一些有明顯漏洞的算法,比如RC4在2013年就被證明不安全,2015年IETF在RFC 7465中禁用了RC4;IETF于2011年發布的RFC 6151也指出了MD5的問題。此外,TLS 1.0和TLS 1.1也不支持更新更安全的算法。IETF認為廢棄老舊版本更安全,支持的版本少了。實現起來也更簡單。
1.2.4 TLS 1.2
2008年8月,TLS 1.2發布為RFC 5246,主要關注了架構靈活性和安全問題。
TLS協議從1.0到1.1再到1.2,都是對安全方面的問題進行改進,比如刪除或增加一些加密套件、改變一些計算方法,但改進的東西并不多,卻大大增加了TLS實現和升級的困難。TLS 1.2希望加密套件和算法能更加靈活的指定,不必因為加密算法的更新而實現新協議。在這方面的幾點改進如下。
1)在ClientHello中增加了signature_algorithms參數,可以指定自己支持的簽名和散列算法列表,簽名中增加了一個字段用于指定使用的散列算法。而在TLS 1.1中簽名算法來自于證書,不可以在ClientHello中指定。這個改進也意味著簽名算法可以不與加密套件綁定。
2)特定PRF由密碼套件指定的PRF取代,而非協議固定的算法,TLS 1.0和TLS 1.1都規定了由MD5/SHA-1組合計算的協議特定PRF。這就意味著可以在TLS 1.2中開發使用新的PRF。但TLS 1.2也規定了一些密碼套件必須使用P_SHA256。PRF定義為:

P_hash計算方法是:

3)Finish消息中的verify_data的長度可變,取決于密碼套件(默認值仍為12)。
4)TLS擴展定義和AES密碼套件的規定合并進RFC 4066(后更新為RFC 6066)和RFC 3268。跟具體算法的切割也避免了算法的變化導致協議需要升級。
對于安全方面的改進是TLS版本的必要過程,TLS 1.2的安全改進主要有以下幾個方面。
1)增加了對AEAD(Authenticated Encryption with Associated Data關聯數據認證加密)的支持。AEAD可以在加密中認證沒有加密部分的關聯數據,甚至是不在報文中的關聯數據,可以保護更大的范圍;另外AEAD將消息認證碼(Message Authentication Code,MAC)也進行了加密。TLS 1.2中使用的附加數據包括記錄的序列號、壓縮算法等:

AEAD的計算方法為:

2)規定必須實現密碼套件TLS_RSA_WITH_AES_128_CBC_SHA。
3)增加了HMAC-SHA256密碼套件。
4)刪除了包含已廢棄算法的IDEA和DES密碼套件。
5)對EncryptedPreMasterSecret版本號進行了更嚴格的檢查。
在使用TLS 1.2首次訪問網站的流程中,即使忽略DNS(Domain Name System,域名系統)解析、證書吊銷檢查等環節,正常也需要3-RTT(Round-Trip Time,往返時延)才能夠發送應用數據,如圖1-18所示。為了使用戶感受到更快的連接,希望能夠更早地發送應用數據,在不能夠使用連接恢復的情況下,可以使用TLS 1.2的False Start特性(見RFC 7981),如圖1-19所示,該特性可以讓客戶端在收到服務器Finished消息之前就發送應用數據,首次連接發送應用數據只需要2-RTT。

圖1-18 使用DH算法的TLS 1.2流程

圖1-19 TLS 1.2 False Start特性
1.2.5 TLS 1.3
TLS 1.3于2018年8月發布(版本號0x0304)為RFC 8446,這是迄今為止TLS改變最大的一次版本升級,跟SSLv3.0的握手過程也開始顯著不同。TLS 1.3除增強安全性(如密碼套件的選擇、密鑰的計算方式、握手消息的發送方式)之外,重點改進了連接速度,首次連接發送數據最低可以1-RTT,恢復連接發送數據最低可以0-RTT。
TLS 1.3在安全方面的改進主要有以下幾個方面。
1)刪除了所有被證明有問題的對稱加密算法,只保留了AEAD的加密套件。密碼套件的概念也已經改變,將認證和密鑰交換機制與加密算法和散列(用于密鑰導出函數和握手消息認證碼)分離。
2)刪除RSA和靜態DH密碼套件,因為靜態RSA加密預主密鑰的方式和使用靜態DH私鑰都不能保證前向安全性,很容易泄露密鑰。只保留能保證前向安全的密鑰交換算法,如使用臨時私鑰的ECDHE(Elliptic Curve Diffie-Hellman Ephemeral,橢圓曲線DH臨時密鑰交換算法)和DHE(Diffie-Hellman Ephemeral,DH臨時密鑰交換算法)。
3)ServerHello之后的消息都加密傳輸,像EncryptedExtensions消息、CertificateRequest消息、Certificate消息、CertificateVerify消息等。之前的版本中,TLS擴展在ServerHello消息中以明文發送,新引入的EncryptedExtension消息可以保證服務器擴展以加密方式傳輸。證書也加密傳輸,不會被中間人輕易截獲,增強了證書的保密性。
4)重新設計了密鑰導出函數。使用HKDF(HMAC-based Extract-and-Expand Key Derivation Function,基于HMAC的密鑰導出函數,見RFC 5869)作為密鑰導出函數。
5)分離了握手密鑰和記錄密鑰,重構了握手狀態機,刪除了ChangeCipherSpec、ClientKeyExchange等消息。
6)將ECDHE作為基本規范,添加了新的簽名算法,如EdDSA(Edwards-Curve Digital Signature Algorithm,愛德華茲曲線數字簽名算法),刪除了點格式協商。
7)改變RSA填充以使用RSA概率簽名方案(RSASSA-PSS),刪除DSA和定制DHE組(Ephemeral Diffie-Hellman)。
8)不再使用TLS 1.2的版本協商機制,而是在TLS擴展supported_versions中添加版本列表。為了版本兼容仍然支持ClientHello.legacy_version和ServerHello.legacy_version,但擴展supported_versions在處理上具有更高優先級。
9)改進了會話恢復的方法,使用新的基于PSK(Pre-Shared Key,預共享密鑰)的交換方法。
10)刪除了壓縮功能。之前版本的壓縮功能由于存在被攻擊的風險實際上很少使用,而且現代的壓縮基本都在應用層實現,比如HTTP就自己實現的壓縮。
11)刪除了之前TLS版本中的重協商功能,增加了握手后客戶端認證。
由于第一次數據發送要等好幾個RTT(DNS解析、TCP連接、TLS連接)后才能進行,導致用戶體驗不好。為了盡快發送數據,每個層都做出了努力,如TCP Fast Open。對于TLS來說,業界也做出了一些嘗試,如圖1-20所示,圖1-21a為之前發送數據的方式(客戶端收到服務器的Finished消息后再發送數據),圖1-21b為改進后的方式(客戶端發送完自己的Finished消息后就立即發送數據,不等待服務器的Finished消息)。雖然這樣更早地將應用數據發送出去,但也犧牲了部分安全性,因為客戶端在沒有確定服務器是否可信、消息是否被篡改就發送了應用數據。
TLS 1.3在加快連接速度方面做出了新的嘗試,首次連接最低可以在1-RTT后發送數據,如圖1-21a所示;恢復連接最低可以0-RTT發送數據,如圖1-21b所示。另外,修改了之前版本中使用會話標識恢復連接的做法,改用更安全的ticket來標識特定的PSK,而ticket是在新增加的NewSessionTicket消息中傳遞的,受1-RTT流量密鑰保護。
- 網絡教育學習指導
- Django 2 by Example
- 無人機通信
- 通信簡史:從信鴿到6G+
- Socket.IO Real-time Web Application Development
- Mastering JavaFX 10
- 世界互聯網發展報告·2019
- 城市治理一網統管
- Bonita Open Solution 5.x Essentials
- 網絡環境中基于用戶視角的信息質量評價研究
- 高級網絡技術
- Microsoft Power Platform Enterprise Architecture
- 世界互聯網發展報告2021
- 移動互聯網環境下的核心網剖析及演進
- Hands-On Reactive Programming in Spring 5