TLS1.2協議設計原理

目錄

  • 前言
  • 為什麼需要TLS協議
  • 發展歷史
  • 協議設計目標
  • 記錄協議
    • 握手步驟
    • 握手協議
      • Hello Request
      • Client Hello
      • Server Hello
      • Certificate
      • Server Key Exchange
      • Certificate Request
      • Server Hello Done
      • Client Certificate
      • Client Key Exchange
      • Certificate Verify
      • Finished
    • 改變密碼標準協議
    • 警報協議
    • 應用程序數據協議
  • 結語
  • 參考文獻

前言

最近對TLS1.2協議處理流程進行了學習及實現,本篇文章對TLS1.2的理論知識和處理流程進行分析,TLS協議的實現建議直接看The Transport Layer Security (TLS) Protocol Version 1.2

為什麼需要TLS協議

通常我們使用TCP協議或UDP協議進行網絡通信。TCP協議提供一種面向連接的、可靠的字節流服務。但是TCP並不提供數據的加密,也不提供數據的合法性校驗。

我們通常可以對數據進行加密、簽名、摘要等操作來保證數據的安全。目前常見的加密方式有對稱加密和非對稱加密。使用對稱加密,雙方使用共享密鑰。

但是對於部署在互聯網上的服務,如果我們為每個客戶端都使用相同的對稱加密密鑰,那麼任何人都可以將數據解密,那麼數據的隱私性將得不到保障。

如果我們使用非對稱密鑰加密,客戶端使用服務端的公鑰進行公鑰加密,服務端在私鑰不泄露的情況下,只有服務端可以使用私鑰可以對數據進行解密,從而保障數據的隱私性,但是非對稱加密比對稱加密的成本高得多。

我們可以採用對稱加密和非對稱加密相結合的方式實現數據的隱私性的同時性能又不至於太差。

  1. 首先客戶端和服務端通過一個稱為密鑰交換的流程進行密鑰協商及交換密鑰所系的信息。
  2. 通過公鑰加密對稱密鑰保證對稱密鑰的安全傳輸。
  3. 服務端使用私鑰解密出對稱密鑰。
  4. 最後雙方使用協商好的對稱密鑰對數據進行加解密。

TLS協議就是實現了這一過程安全協議。TLS是在TCP之上,應用層之下實現的網絡安全方案。在TCP/IP四層網絡模型中屬於應用層協議。TLS協議在兩個通信應用程序之間提供數據保密性和數據完整性,另外還提供了連接身份可靠性方案。

UDP則使用DTLS協議實現安全傳輸,和TLS協議類似。

發展歷史

TLS協議的前身SSL協議是網景公司設計的主要用於Web的安全傳輸協議,這種協議在Web上獲得了廣泛的應用。

  • 1994年,網景公司設計了SSL協議的1.0版,因為存在嚴重的安全漏洞,未公開。
  • 2.0版本在1995年2月發布,但因為存在數個嚴重的安全漏洞(比如使用MD5摘要、握手消息沒有保護等),2011年RFC 6176 標準棄用了SSL 2.0。
  • 3.0版本在1996年發布,是由網景工程師完全重新設計的,同時寫入RFC,較新版本的SSL/TLS基於SSL 3.0。2015年,RFC 7568 標準棄用了SSL 3.0。
  • 1999年,IETF將SSL標準化,並將其稱為TLS(Transport Layer Security)。從技術上講,TLS 1.0與SSL 3.0的差異非常微小。
  • TLS 1.1在RFC 4346中定義,於2006年4月發表,主要修復了CBC模式的BEAST攻擊等漏洞。

    微軟、Google、蘋果、Mozilla四家瀏覽器業者將在2020年終止支持TLS 1.0及1.1版。

  • TLS 1.2在RFC 5246中定義,於2008年8月發表,添加了增加AEAD加密算法,如支持GCM模式的AES。
  • TLS 1.3在RFC 8446中定義,於2018年8月發表,砍掉了AEAD之外的加密方式。

協議設計目標

  1. 加密安全:TLS應用於雙方之間建立安全連接,通過加密,簽名,數據摘要保障信息安全。
  2. 互操作性:程序員在不清楚TLS協議的情況下,只要對端代碼符合RFC標準的情況下都可以實現互操作。
  3. 可擴展性:在必要時可以通過擴展機制添加新的公鑰和機密方法,避免創建新協議。
  4. 相對效率:加密需要佔用大量CPU,尤其是公鑰操作。TLS協議握手完成后,通過對稱密鑰加密數據。TLS還集成了會話緩存方案,減少需要從頭建立連接的情況。

記錄協議

TLS協議是一個分層協議,第一層為TLS記錄層協議(Record Layer Protocol),該協議用於封裝各種高級協議。目前封裝了4種協議:握手協議(Handshake Protocol)、改變密碼標準協議(Change Cipher Spec Protocol)、應用程序數據協議(Application Data Protocol)和警報協議(Alert Protocol)。

Change Cipher Spec Protocol在TLS1.3被去除。

記錄層包含協議類型、版本號、長度、以及封裝的高層協議內容。記錄層頭部為固定5字節大小。

在TLS協議規定了,如接收到了未定義的協議協議類型,需要發送一個unexpected_message警報。

握手步驟

  • 當客戶端連接到支持TLS協議的服務端要求創建安全連接並列出了受支持的算法套件(包括加密算法、散列算法等),握手開始。
  • 服務端從客戶端的算法套件列表中指定自己支持的一個算法套件,並通知客戶端,若沒有則使用一個默認的算法套件。
  • 服務端發回其数字證書,此證書通常包含服務端的名稱、受信任的證書頒發機構(CA)和服務端的公鑰。
  • 客戶端確認其頒發的證書的有效性。
  • 為了生成會話密鑰用於安全連接,客戶端使用服務端的公鑰加密隨機生成的密鑰,並將其發送到服務端,只有服務端才能使用自己的私鑰解密。
  • 利用隨機數,雙方生成用於加密和解密的對稱密鑰。這就是TLS協議的握手,握手完畢后的連接是安全的,直到連接(被)關閉。如果上述任何一個步驟失敗,TLS握手過程就會失敗,並且斷開所有的連接。

握手協議

TLS 握手協議允許服務端和客戶端相互進行身份驗證,並在應用程序協議傳輸或接收其第一個字節數據之前協商協議版本、會話ID、壓縮方法、密鑰套件、以及加密密鑰。

完整的TLS握手流程,流程如下

  Client                                                       Server

  ClientHello                  -------->
                                                          ServerHello
                                                          Certificate*
                                                    ServerKeyExchange*
                                                  CertificateRequest*
                                <--------              ServerHelloDone
  Certificate*
  ClientKeyExchange
  CertificateVerify*
  [ChangeCipherSpec]
  Finished                     -------->
                                                    [ChangeCipherSpec]
                                <--------                     Finished
  Application Data             <------->             Application Data
  • 表示可選步驟或與實際握手情況相關。比如重建已有連接,服務端無需執行Certificate,再比如使用RSA公鑰加密時,無需ServerKeyExchange。
    握手協議消息必須按上面流程的發送數據進行發送,否則需要以致命錯誤告知對方並關閉連接。

完整的握手流程有時候也被稱為2-RTT流程,即完整的握手流程需要客戶端和服務端交互2次才能完成握手。

交互應用請求到響應的交互時間被稱為往返時間(Round-trip Time)

握手協議的結構如下,其中協議頭的ContentType固定為22,接下來是TLS版本號,TLS1.2為0303,最後是用2字節表示長度。

握手協議類型包含以下:

  • hello_request:0
  • client_hello:1
  • server_hello:2
  • certificate:3
  • server_key_exchange :12
  • certificate_request:13
  • server_hello_done:14
  • certificate_verify:15
  • client_key_exchange:16
  • finished:20

Hello Message是具體的握手協議類型內容,不同協議內容有所不同。

Hello Request

Hello Request消息用於客戶端與服務端重新協商握手,該消息可能由服務端在任何時刻發送。Hello Request消息非常簡單,沒有其他冗餘信息。

當客戶端收到了服務端的Hello Request時可以有以下4種行為:

  • 當客戶端正在協商會話,可以忽略該消息。
  • 若客戶端未在協商會話但不希望重新協商時,可以忽略該消息。
  • 若客戶端未在協商會話但不希望重新協商時,可以發送no_renegotiation警報。
  • 若客戶端希望重新協商會話,則需要發送ClientHello重新進行TLS握手。

服務端發送完HelloRequest消息,可以有以下幾種行為:

  • 服務端發送了HelloRequest消息,但未收到ClientHello時,可以通過致命連接警報關閉連接。
  • 服務端發送了HelloRequest消息,必須等待握手協商處理完成后才可以繼續處理應用數據消息。

Finished和Certificate的握手消息驗證不包括該消息的hash。

Client Hello

當客戶端首次與服務端建立連接或需要重新協商加密握手會話時,需要將Client Hello作為第一條消息發送給服務端。

Client Hello消息包含了許多重要信息,包括客戶端版本號、客戶端隨機數、會話ID、密鑰套件、壓縮方式、擴展字段等。

  • 客戶端版本號:客戶端支持的最新TLS版本號,服務端會根據該協議號進行協議協商。
  • 32位隨機數:客戶端生成的32位隨機數。前4位是Unix時間戳,該時間戳為1970年1月1日0點以來的秒數。不過TLS並沒有強制要求校驗該時間戳,因此允許定義為其他值。後面28位為一個隨機數。

    通過前4字節填寫時間方式,有效的避免了周期性的出現一樣的隨機數。使得”隨機”更加”隨機”。
    在TLS握手時,客戶端和服務端需要協商數據傳輸時的加密密鑰。為了保證加密密鑰的安全性。密鑰需要通過客戶端和服務端一起生成。客戶端和服務端都提供一個32位的隨機數,通過該隨機數使用基於HMAC的PRF算法生成客戶端和服務端的密鑰。

  • 會話ID:用於表示客戶端和服務端之間的會話。實際的會話ID是由服務端定義的,因此即使是新的連接,服務端返回的會話ID可能也會和客戶端不一致,由於會話ID是明文傳輸的,因此不能存放機密信息。
    • 若會話ID是新的,則客戶端和服務端需要建立完整的TLS握手連接流程。
    • 若會話ID是較早連接的會話ID,則服務端可以選擇無需執行完整的握手協議。
  • 算法套件:客戶端將支持的加密算法組合排列后發送給服務端,從而和服務端協商加密算法。服務端根據支持算法在ServerHello返回一個最合適的算法組合。
    算法套件的格式為TLS_密鑰交換算法_身份認證算法_WITH_對稱加密算法_消息摘要算法,比如TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,密鑰交換算法是DHE,身份認證算法是RSA,對稱加密算法是AES_256_CBC,消息摘要算法是SHA256,由於RSA又可以用於加密也可以用於身份認證,因此密鑰交換算法使用RSA時,只寫一個RSA,比如TLS_RSA_WITH_AES_256_CBC_SHA256
  • 壓縮方式:用於和服務端協商數據傳輸的壓縮方式。由於TLS壓縮存在安全漏洞,因此在TLS1.3中已經將TLS壓縮功能去除,TLS1.2算法也建議不啟用壓縮功能。
  • 擴展字段:可以在不改變底層協議的情況下,添加附加功能。客戶端使用擴展請求其他功能,服務端若不提供這些功能,客戶端可能會中止握手。對於擴展字段的詳細定義可以看Transport Layer Security (TLS) Extensions

客戶端發送完 ClientHello 消息后,將等待 ServerHello 消息。 服務端返回的任何握手消息(HelloRequest 除外)將被視為致命錯誤。

Server Hello

當服務端接收到ClientHello,則開始TLS握手流程, 服務端需要根據客戶端提供的加密套件,協商一個合適的算法簇,其中包括對稱加密算法、身份驗證算法、非對稱加密算法以及消息摘要算法。若服務端不能找到一個合適的算法簇匹配項,則會響應握手失敗的預警消息。

  • 版本號:服務端根據客戶端發送的版本號返回一個服務端支持的最高版本號。若客戶端不支持服務端選擇的版本號,則客戶端必須發送protocol_version警報消息並關閉連接。

    若服務端接收到的版本號小於當前支持的最高版本,且服務端希望與舊客戶端協商,則返回不大於客戶端版本的服務端最高版本。
    若服務端僅支持大於client_version的版本,則必須發送protocol_version警報消息並關閉連接。
    若服務端收到的版本號大於服務端支持的最高版本的版本,則必須返回服務端所支持的最高版本。

  • 32位隨機數:服務端生成的32位隨機數,生成方式和客戶端一樣。服務端生成隨機數的可以有效的防範中間人攻擊,主要是通過防止重新握手后的重放攻擊。

  • 會話ID:用於表示客戶端和服務端之間的會話。若客戶端提供了會話ID,則可以校驗是否與歷史會話匹配。

    • 若不匹配,則服務端可以選擇直接使用客戶端的會話ID或根據自定義規則生成一個新的會話ID,客戶端需要保存服務端返回的會話ID當作本次會話的ID。

    • 若匹配,則可以直接執行1-RTT握手流程,返回ServerHello后直接返回ChangeCipherSpecFinished消息。

          Client                                                Server
      
          ClientHello                   -------->
                                                          ServerHello
                                                      [ChangeCipherSpec]
                                          <--------             Finished
          [ChangeCipherSpec]
          Finished                      -------->
          Application Data              <------->     Application Data
      

      在Finished消息中和完整握手一樣都需要校驗VerifyData。

  • 算法套件:服務端根據客戶端提供的算法套件列表和自己當前支持算法進行匹配,選擇一個最合適的算法組合,若沒有匹配項,則使用默認的TLS_RSA_WITH_AES_128_CBC_SHA

    TLS1.2協議要求客戶端和服務端都必須實現密碼套件TLS_RSA_WITH_AES_128_CBC_SHA

  • 壓縮方式:用於和服務端協商數據傳輸的壓縮方式。由於TLS壓縮存在安全漏洞,因此在TLS1.3中已經將TLS壓縮功能去除,TLS1.2算法也建議不啟用壓縮功能。

  • 擴展字段:服務端需要支持接收具有擴展和沒有擴展的ClientHello。服務端響應的擴展類型必須是ClientHello出現過才行,否則客戶端必須響應unsupported_extension嚴重警告並中斷握手。

RFC 7568要求客戶端和服務端握手時不能發送{3,0}版本,任何收到帶有協議Hello消息的一方版本設置為{3,0}必須響應protocol_version警報消息並關閉連接。

通過ClientHelloServerHello,客戶端和服務端就協商好算法套件和用於生成密鑰的隨機數。

Certificate

假設客戶端和服務端使用默認的TLS_RSA_WITH_AES_128_CBC_SHA算法,在ServerHello完成后,服務端必須將本地的RSA證書傳給客戶端,以便客戶端和服務端之間可以進行非對稱加密保證對稱加密密鑰的安全性。
RSA的證書有2個作用:

  • 客戶端可以對服務端的證書進行合法性進行校驗。
  • Client Key Exchange生成的pre-master key進行公鑰加密,保證只有服務端可以解密,確保對稱加密密鑰的安全性。

發送給客戶端的是一系列證書,服務端的證書必須排列在第一位,排在後面的證書可以認證前面的證書。
當客戶端收到了服務端的ServerHello時,若客戶端也有證書需要服務端驗證,則通過該握手請求將客戶端的證書發送給服務端,若客戶端沒有證書,則無需發送證書請求到服務端。

證書必須為X.509v3格式。

Server Key Exchange

使用RSA公鑰加密,必須要保證服務端私鑰的安全。若私鑰泄漏,則使用公鑰加密的對稱密鑰就不再安全。同時RSA是基於大數因式分解。密鑰位數必須足夠大才能避免密鑰被暴力破解。

1999年,RSA-155 (512 bits) 被成功分解。
2009年12月12日,RSA-768 (768 bits)也被成功分解。
在2013年的稜鏡門事件中,某個CA機構迫於美國政府壓力向其提交了CA的私鑰,這就是十分危險的。

相比之下,使用DH算法通過雙方在不共享密鑰的情況下雙方就可以協商出共享密鑰,避免了密鑰的直接傳輸。DH算法是基於離散對數,計算相對較慢。而基於橢圓曲線密碼(ECC)的DH算法計算速度更快,而且用更小的Key就能達到RSA加密的安全級別。ECC密鑰長度為224~225位幾乎和RSA2048位具有相同的強度。

ECDH:基於ECC的DH算法。

另外在DH算法下引入動態隨機數,可以避免密鑰直接傳輸。同時即使密鑰泄漏,也無法解密其他消息,因為雙方生成的動態隨機數無法得知。

在密碼學中該特性被稱為前向保密

DHE: 通過引入動態隨機數,具有前向保密的DH算法。
ECDHE:通過引入動態隨機數,具有前保密的ECDH算法。

Certificate Request

當需要TLS雙向認證的時候,若服務端需要驗證客戶端的證書,則向客戶端發送Certificate Request請求獲取客戶端指定類型的證書。

  • 服務端會指定客戶端的證書類型。
  • 客戶端會確定是否有合適的證書。

Server Hello Done

當服務端處理Hello請求結束時,發送Server Hello Done消息,然後等待接收客戶端握手消息。客戶端收到服務端該消息,有必要時需要對服務端的證書進行有效性校驗。

Client Certificate

當客戶端收到了服務端的CertificateRequest請求時,需要發送Client Certificate消息,若客戶端無法提供證書,則仍要發送此消息,消息內容可以不包含證書。

Client Key Exchange

客戶端接收到ServerHelloDone消息后,計算密鑰,通過發送Client Key Exchange消息給服務端。客戶端和服務端通過Key Exchange消息交換密鑰,使得雙方的主密鑰協商達成一致。

以RSA的密鑰協商為例。在ClientHelloServerHello分別在客戶端和服務端創建了一個32位的隨機數。客戶端接收到Server Hello Done消息時,生成最後一個48位的預主密鑰。通過服務端提供的證書進行公鑰加密,以保證只有服務端的私鑰才能解密。

其中預主密鑰的前2位要求使用Client Hello傳輸的TLS版本號(存在一些TLS客戶端傳遞的時協商后的TLS版本號,對該版本號檢查時可能會造成握手失敗)。

需要注意的是,若RSA證書的填空格式不正確,則可能會存在一個漏洞導致客戶端發送的PreMasterSecret被中間人解密造成數據加密的對賬密鑰泄漏。可以看下Attacking RSA-based Sessions in SSL/TLS

Certificate Verify

若服務端要求客戶端發送證書,且客戶端發送了非0長度的證書,此時客戶端想要證明自己擁有該證書,則需要使用客戶端私鑰簽名一段數據發送給服務端繼續驗證。該數據為客戶端收發的所有握手數據的hash值(不包括本次消息)。

Finished

當發送完Change Cipher Spec消息后必須立即發送該消息。當該消息用於驗證密鑰交換和身份驗證過程是否成功。

Finished消息是第一個使用協商的算法簇進行加密和防篡改保護的消息。一旦雙方都通過了該消息驗證,就完成了TLS握手。
VerifyData為客戶端收發的所有握手數據的hash值(不包括本次消息)。與Certificate Verify的hash值可能會不一樣。如果發送過Certificate Verify消息,服務端的握手消息會包含Certificate Verify握手的數據。

需要注意的是,握手數據不包括協議頭的握手協議明文數據(服務端返回Finished的驗證握手數據是包含接收到客戶端的Finished的明文hash值)。

Finished消息數據加密和Appilication Data一致,具體數據加密在Application Data段進行說明。

改變密碼標準協議

改變密碼標準協議是為了在密碼策略中發出信號轉換信號。 該協議由一條消息組成,該消息在當前(不是掛起的)連接狀態下進行加密和壓縮。 消息由值 1 的單個字節組成。

在接收到該協議后,所有接收到的數據都需要解密。

警報協議

警報消息傳達消息的嚴重性(警告或致命)和警報的說明。具有致命級別的警報消息會導致立即終止連接。
若在改變密碼標準協議前接收到警報消息,是明文傳輸的,無需解密。

與其他消息一樣,警報消息按當前連接狀態指定進行加密和壓縮。在接收到改變密碼標準協議後接收到警報協議,則需要進行解密。解密后即為警報協議明文格式。

加密的Alert消息和加密數據一樣,都需要遞增加密序號,在數據解密時,遞增解密序號。

應用程序數據協議

當客戶端和服務端Finished發送完畢並驗證通過後,握手就結束了。後續所有數據都會使用握手協商的對稱密鑰進行數據加密。

TLS協議實現了數據加密和MAC計算。一般來說有3種加密模式,分別為:

  1. Mac-then-Encrypt:在明文上計算MAC,將其附加到數據,然後加密明和+MAC的完整數據。
  2. 加密和MAC:在明文上計算MAC,加密明文,然後將MAC附加到密文的末尾
  3. Encrypt-then-Mac:加密明文,然後在密文上計算MAC,並將其附加到密文。

TLS協議使用的是Mac-then-Encrypt。首先將加密的序號、ContentType、數據長度、數據進計算HMAC-SHA256摘要。然後將摘要拼接到數據后,通過PKCS7格式對摘要+MAC數據進行填充對其和加密塊大小一致。最後摘要+MAC+對其填充塊進行加密。

需要注意的是應用程序數據消息有最大長度限制2^14 + 2048,當超過長度后,數據需要分段傳輸。每一段都當作單獨的數據段進行單獨MAC地址並加密。

結語

TLS1.2版本是目前最常用的TLS協議,TLS1.3版本於2018年發表,目前並沒有廣泛使用。
使用TLS1.2需要注意以下幾點:

  1. 若使用RSA非對稱加密,則需要盡可能使用2048位長度的密鑰。
  2. 盡可能可以使用具有前向安全性的加密算法,如ECDHE算法進行非對稱加密。
  3. 使用AEAD認證加密(GCM)代替CBC塊加密。

參考文獻

  1. The Transport Layer Security (TLS) Protocol Version 1.2
  2. TLS發展歷史
  3. 前向安全性
  4. TLS/SSL 協議詳解 (30) SSL中的RSA、DHE、ECDHE、ECDH流程與區別
  5. TLS Extensions
  6. Session會話恢復:兩種簡短的握手總結SessionID&SessionTicket
  7. Why using the premaster secret directly would be vulnerable to replay attack?
  8. Why does the SSL/TLS handshake have a client and server random?
  9. Transport Layer Security (TLS) Extensions
  10. 什麼是AEAD加密
  11. Padding Oracle Attacks
  12. Lucky13攻擊
  13. Padding Oracle Attack
  14. ssl perfect forward secrecy
  15. Transport Layer Security (TLS) Session Resumption without Server-Side State
  16. Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS)
  17. DTLS協議中client/server的認證過程和密鑰協商過程

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

網頁設計最專業,超強功能平台可客製化

您可能也會喜歡…