您好,登錄后才能下訂單哦!
這篇文章主要講解了“什么是DTLS協(xié)議”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“什么是DTLS協(xié)議”吧!
DTLS (Datagram Transport Layer Security) 基于 UDP 場(chǎng)景下數(shù)據(jù)包可能丟失或重新排序的現(xiàn)實(shí)情況下,為 UDP 定制和改進(jìn)的 TLS 協(xié)議。在 WebRTC 中使用 DTLS 的地方包括兩部分:協(xié)商和管理 SRTP 密鑰和為 DataChannel 提供加密通道。
本文結(jié)合實(shí)際數(shù)據(jù)包分析 WebRTC 使用 DTLS 進(jìn)行 SRTP 密鑰協(xié)商的流程。并對(duì)在實(shí)際項(xiàng)目中使用 DTLS 遇到的問(wèn)題進(jìn)行總結(jié)。
在分析 DTLS 在 WebRTC 中的應(yīng)用之前,先介紹下 DTLS 協(xié)議的基本原理。DTLS 協(xié)議由兩層組成: Record 協(xié)議 和 Handshake 協(xié)議
Record 協(xié)議:使用對(duì)稱密鑰對(duì)傳輸數(shù)據(jù)進(jìn)行加密,并使用 HMAC 對(duì)數(shù)據(jù)進(jìn)行完整性校驗(yàn),實(shí)現(xiàn)了數(shù)據(jù)的安全傳輸。
Handshake 協(xié)議:使用非對(duì)稱加密算法,完成 Record 協(xié)議使用的對(duì)稱密鑰的協(xié)商。
TLS 握手協(xié)議流程如下,參考 RFC5246
DTLS 握手協(xié)議流程如下,參考 RFC6347
TLS 和 DTLS 的握手過(guò)程基本上是一致的,差別以及特別說(shuō)明如下:
DTLS 中 HelloVerifyRequest 是為防止 DoS 攻擊增加的消息。
TLS 沒(méi)有發(fā)送 CertificateRequest,這個(gè)也不是必須的,是反向驗(yàn)證即服務(wù)器驗(yàn)證客戶端。
DTLS 的 RecordLayer 新增了 SequenceNumber 和 Epoch,以及 ClientHello 中新增了 Cookie,以及 Handshake 中新增了 Fragment 信息(防止超過(guò) UDP 的 MTU),都是為了適應(yīng) UDP 的丟包以及容易被攻擊做的改進(jìn)。參考 RFC 6347
DTLS 最后的 Alert 是將客戶端的 Encrypted Alert 消息,解密之后直接響應(yīng)給客戶端的,實(shí)際上 Server 應(yīng)該回應(yīng)加密的消息,這里我們的服務(wù)器回應(yīng)明文是為了解析客戶端加密的那個(gè) Alert 包是什么。
RecordLayer 協(xié)議是和 DTLS 傳輸相關(guān)的協(xié)議,UDP 之上是 RecordLayer,RecordLayer 之上是 Handshake 或 ChangeCipherSpec 或 ApplicationData。RecordLayer 協(xié)議定義參考 RFC4347,實(shí)際上有三種 RecordLayer 的包:
DTLSPlaintext
,DTLS 明文的 RecordLayer。
DTLSCompressed
,壓縮的數(shù)據(jù),一般不用。
DTLSCiphertext
,加密的數(shù)據(jù),在 ChangeCipherSpec 之后就是這種了。
沒(méi)有明確的字段說(shuō)明是哪種消息,不過(guò)可以根據(jù)上下文以及內(nèi)容判斷。比如 ChangeCipherSpec 是可以通過(guò)類型,它肯定是一個(gè) Plaintext。除了 Finished 的其他握手,一般都是 Plaintext。
在 DTLS 協(xié)議,通信的雙方有 Client
和 Server
之分。在 WebRTC 中 DTLS 協(xié)商的身份是在 SDP
中描述的。描述如下,參考 SDP-Anatomy 中 DTLS 參數(shù)
a=setup:active
setup
屬性在 RFC4145,
setup:active,作為 client,主動(dòng)發(fā)起協(xié)商
setup:passive, 作為 sever,等待發(fā)起協(xié)商
setup:actpass, 作為 client,主動(dòng)發(fā)起協(xié)商。作為 server,等待發(fā)起協(xié)商。
ClienHello 和 ServerHello 協(xié)商 DTLS 的 Version、CipherSuites、Random、以及 Extensions。
Version
:Client 給出自己能支持的、或者要使用的最高版本,比如 DTLS1.2。Server 收到這個(gè)信息后,根據(jù)自己能支持的、或者要使用的版本回應(yīng),比如 DTLS1.0。最終以協(xié)商的版本也就是 DTLS1.0 為準(zhǔn)。
CipherSuites
:Client 給出自己能支持的加密套件 CipherSuites,Server 收到后選擇自己能支持的回應(yīng)一個(gè),比如 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014),加密套件確定了證書(shū)的類型、密鑰生成算法、摘要算法等。
Random
:雙方的隨機(jī)數(shù),參與到生成 MasterSecret。MasterSecret 會(huì)用來(lái)生成主密鑰,導(dǎo)出 SRTP 密鑰。詳見(jiàn) [導(dǎo)出 SRTP 密鑰]
Extensions
:Client 給出自己要使用的擴(kuò)展協(xié)議,Server 可以回應(yīng)自己支持的。比如 Client 雖然設(shè)置了 SessionTicket TLS 這個(gè)擴(kuò)展,但是 Server 沒(méi)有回應(yīng),所以最終并不會(huì)使用這個(gè)擴(kuò)展。
在 Hello 消息中加密套接字使用 IANA
中的注冊(cè)的名字。IANA 名字由 Protocol,Key Exchange Algorithm,Authentication Algorithm,Encryption Algorithm ,Hash Algorithm 的描述組成。例如,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 的含義如下:
Protocol
: Transport Layer Security (TLS)
Key Exchange
: Elliptic Curve Diffie-Hellman Ephemeral (ECDHE)
Authentication
: Rivest Shamir Adleman algorithm (RSA)
Encryption
: Advanced Encryption Standard with 128bit key in Galois/Counter mode (AES 128 GCM)
Hash
: Secure Hash Algorithm 256 (SHA256)
加密套接字在 ciphersuite.info 可以查到。在查到 IANA 名字的同時(shí),也可以查到在 OpenSSL 中的名字。TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 在 OpenSSL 中的名字為 ECDHE-RSA-AES128-GCM-SHA256 Note: 關(guān)于 Authentication (認(rèn)證)、KeyExchange (密鑰交換)、Encryption (加密)、MAC (Message Authentication Code) 消息摘要等,可以參考 RSA 密鑰協(xié)商。
DTLS 的擴(kuò)展協(xié)議,是在 ClientHello 和 ServerHello 的 Extensions 信息中指定的,所有的 TLS 擴(kuò)展參考 TLS Extensions。下面列出幾個(gè) WebRTC 用到的擴(kuò)展:
use_srtp
: DTLS 握手完成后 (Finished),使用 SRTP 傳輸數(shù)據(jù),DTLS 生成 SRTP 的密鑰。 RFC5764。ClientHello 中的擴(kuò)展信息定義了 RFC5764 4.1.2. SRTP Protection Profiles 和 srtp_mki。
supported_groups
,原來(lái)的名字為 elliptic_curves,描述支持的 ECC 加密算法,參考 RFC8422 5.1.1.Supported Elliptic Curves Extension,一般用的是 secp256r1。
signature_algorithms
,DTLS1.2 的擴(kuò)展,指定使用的 Hash 和 Signature 算法,參考 RFC5246 7.4.1.4.1. Signature Algorithms。DTLS1.0,RSA 用的是 md5sha1 摘要算法,DSA 用的是 sha1 摘要算法。
extended_master_secret
,擴(kuò)展 MasterSecret 的生成方式,參考 RFC7627。在 KeyExchange 中,會(huì)加入一些常量來(lái)生成 MasterSecret。TLS 定義了擴(kuò)展方式,如果用這個(gè)擴(kuò)展,DTLS 的方式和 TLS 會(huì)有些不同。
renegotiation_info
, 參考 RFC5746
除了這些擴(kuò)展協(xié)議,和 SRTP 密鑰導(dǎo)出相關(guān)的還有:
RFC5705: Keying Material Exporters for Transport Layer Security (TLS),DTLS 如何從 MasterSecret 導(dǎo)出 Key,比如 SRTP 的 Key。 RFC5764: DTLS Extension to Establish Keys for the SRTP,DTLS 的 use_srtp 擴(kuò)展的詳細(xì)規(guī)范,包括 ClientHello 擴(kuò)展定義、Profile 定義、Key 的計(jì)算。
數(shù)字證書(shū)是由一些公認(rèn)可信的證書(shū)頒發(fā)機(jī)構(gòu)簽發(fā)的,不易偽造。數(shù)字證書(shū)可以用于接收者驗(yàn)證對(duì)端的身份,接收者收到某個(gè)對(duì)端的證書(shū)時(shí),會(huì)對(duì)簽名頒發(fā)機(jī)構(gòu)的數(shù)字簽名進(jìn)行檢查,一般來(lái)說(shuō),接收者事先就會(huì)預(yù)先安裝很多常用的簽名頒發(fā)機(jī)構(gòu)的證書(shū)(含有公開(kāi)密鑰),利用預(yù)先的公開(kāi)密鑰可以對(duì)簽名進(jìn)行驗(yàn)證。
Server 端通過(guò) Hello 消息,協(xié)商交換密鑰的方法后,將 Server 證書(shū)發(fā)送給 Client,用于 Client 對(duì) Server 的身份進(jìn)行校驗(yàn)。Server 發(fā)送的證書(shū)必須適用于協(xié)商的 KeyExchange 使用的加密套接字,以及 Hello 消息擴(kuò)展中描述的 Hash/Signature 算法對(duì)。
在 WebRTC 中,通信的雙方通常將無(wú)法獲得由知名根證書(shū)頒發(fā)機(jī)構(gòu) (CA) 簽名的身份驗(yàn)證證書(shū),自簽名證書(shū)通常是唯一的選擇。RFC4572 定義一種機(jī)制,通過(guò)在 SDP
中增加自簽名證書(shū)的安全哈希,稱為 "證書(shū)指紋",在保證 SDP 安全傳輸?shù)那疤嵯?,如果提供的證書(shū)的指紋與 SDP
中的指紋匹配,則可以信任自簽名證書(shū)。在實(shí)際的應(yīng)用場(chǎng)景中,SDP 在安全的信令通道 (https) 完成交換的,SDP 的安全完整是可以做到的。這樣在 DTLS 協(xié)商過(guò)程中,可以使用證書(shū)的指紋,完成通信雙方的身份校驗(yàn)。證書(shū)指紋在 SDP 中的描述如下,參考 SDP-Anatomy 中 DTLS 參數(shù)
a=fingerprint:sha-256 49:66:12:17:0D:1C:91:AE:57:4C:C6:36:DD:D5:97:D2:7D:62:C9:9A:7F:B9:A3:F4:70:03:E7:43:91:73:23:5E
ServerKeyExchange 用來(lái)將 Server 端使用的公鑰,發(fā)送給 Client 端。分為兩種情況:
RSA
算法:如果服務(wù)端使用的是 RSA 算法,可以不發(fā)送這個(gè)消息,因?yàn)?RSA 算法使用的公鑰已經(jīng)在 Certificate 中描述。
DH
算法,是根據(jù)對(duì)方的公鑰和自己私鑰計(jì)算共享密鑰。因?yàn)?Client 和 Server 都只知道自己的私鑰,和對(duì)方的公鑰;而他們的私鑰都不同,根據(jù)特殊的數(shù)學(xué)特性,他們能計(jì)算出同樣的共享密鑰。關(guān)于 DH 算法如何計(jì)算出共享密鑰,參考 DH 算法。
ClientKeyExchange 用來(lái)將 Client 使用的公鑰,發(fā)送給 Server 端。
RSA
算法:如果密鑰協(xié)商使用的 RSA 算法,發(fā)送使用 server 端 RSA 公鑰,對(duì) premaster secret 加密發(fā)送給 server 端。
DH
算法:如果密鑰協(xié)商使用的 DH 算法,并且在證書(shū)中沒(méi)有描述,在將客戶端使用的 DH 算法公鑰發(fā)送給 Server 端,以便計(jì)算出共享密鑰。 KeyExchange 的結(jié)果是,Client 和 Server 獲取到了 RSA Key, 或通過(guò) DH 算法計(jì)算出共享密鑰。詳見(jiàn) [導(dǎo)出 SRTP 密鑰] 的過(guò)程
使用 ClientRequest 中描述的 Hash/Signature 算法,對(duì)收到和發(fā)送的 HandShake 消息簽名發(fā)送個(gè) Server。Server 端對(duì)簽名進(jìn)行校驗(yàn)。
當(dāng) Server 和 Client 完成對(duì)稱密鑰的交換后,通過(guò) ChangeCipherSpec
通知對(duì)端進(jìn)入加密階段,epoch 加 1。
隨后 Client 使用交換的密鑰,對(duì) "client finished" 加密,使用 Finished 消息,發(fā)送給服務(wù)端。Server 使用交換的密鑰,對(duì) "server finished" 進(jìn)行加密發(fā)送給客戶端。一旦驗(yàn)證了 finished 消息后,就可以正常通信了。
上面介紹了 DTLS 的過(guò)程,以下通過(guò)結(jié)合上面例子給出的實(shí)際數(shù)據(jù),詳細(xì)說(shuō)明 SRTP 密鑰的導(dǎo)出步驟。
加密套件:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) 橢圓曲線算法為:secp256r1,橢圓曲線的點(diǎn)壓縮算法為:uncompressed。 橢圓曲線算法的基礎(chǔ)知識(shí)的介紹在 ECC 橢圓曲線加密算法 - ECDH,ECDHE,ECDSA ,由文檔中我們可以知道,確定橢圓曲線加密算法有如下參數(shù):
素?cái)?shù) p,用于確定有限域的范圍
橢圓曲線方程中的 a,b 參數(shù)
用于生成子群的的基點(diǎn) G
子群的階 n
子群的輔助因子 h 定義為六元組(p,a,b,G,n,h)
通過(guò)在 SECG-SEC2 2.4.2 Recommended Parameters secp256r1 中可以查到 secp256r1 對(duì)應(yīng)的參數(shù)如下:
secp256r1使用的參數(shù)如下: 使用的素?cái)?shù)p: p=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF =2224(232?1)+2192+296?1 橢圓曲線E:y^2=x^3+ax+b的參數(shù)定義如下: a=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC b=5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B 基點(diǎn)G的非壓縮格式: G=046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5 有限域的階n: n=FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 輔助因子h: h=01
ECDH Server Parameter
Pubkey:04b0ce3c5f2c4a9fbe7c2257c1328438f3378f74e9f528b6e27a00b44eee4c19e5e6b2cb6cab09f796bcf8c05102b2a4bcdc753d91cc4f431f558c845a1ba6f1ce
記為 Spk
ECDH Client Paramter
PubKey: 0454e8fbef1503109d619c39be0ccaf89efa3c3962300476465cbc66b15152cd8a900c45d506420f0123e65d8fbb70cb60b497893f81c5c2a0ef2f4bc2da996d9e
記為 Cpk
假設(shè) Server 的使用的橢圓曲線私鑰為 Ds, Client 使用的 Dc,計(jì)算共享密鑰的如下,參考 ECC 橢圓曲線加密算法 - ECDH,ECDHE,ECDSA
S = Ds * Cpk = Dc * Spk
這個(gè)共享密鑰 S
就是我們?cè)?RFC 文檔中看到的 pre-master-secret
計(jì)算 master secret
過(guò)程如下,可參考 Computing the Master Secret
master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random)[0..47];
計(jì)算出來(lái)的 master_secret
為 48 Bytes,其中 ClientHello.random
和 ServerHello.random
在 Hello 消息中給出。PRF
是偽隨機(jī)數(shù)函數(shù) (pseudorandom function),在協(xié)商的加密套件中給出。
使用 RFC5705 4. Exporter Definition 給出的計(jì)算方式,使用參數(shù) master_secret
, client_random
,server_random
計(jì)算字節(jié)序列:
key_block = PRF(master_secret, "EXTRACTOR-dtls_srtp", client_random + server_random)[length]
在 DTLS-SRTP 4.2. Key Derivation 中描述了需要的字節(jié)序列長(zhǎng)度。
2 * (SRTPSecurityParams.master_key_len + SRTPSecurityParams.master_salt_len) bytes of data
master_key_len 和 master_salt_len 的值,在 user_srtp
描述的 profile 中定義。我們的實(shí)例中使用的 profile 為 SRTP_AES128_CM_HMAC_SHA1_80
,對(duì)應(yīng)的 profile 配置為:
SRTP_AES128_CM_HMAC_SHA1_80 cipher: AES_128_CM cipher_key_length: 128 cipher_salt_length: 112 maximum_lifetime: 2^31 auth_function: HMAC-SHA1 auth_key_length: 160 auth_tag_length: 80
也就是我們需要 (128/8+112/8)*2 = 60 bytes
字節(jié)序列。
計(jì)算出 SRTP 加密參數(shù)字節(jié)序列,在 DTLS-SRTP 4.2. Key Derivation 描述了字節(jié)序列的含義:
client_write_SRTP_master_key[SRTPSecurityParams.master_key_len]; // 128 bits server_write_SRTP_master_key[SRTPSecurityParams.master_key_len]; // 128 bits client_write_SRTP_master_salt[SRTPSecurityParams.master_salt_len]; // 112 bits server_write_SRTP_master_salt[SRTPSecurityParams.master_salt_len]; // 112 bits
至此我們得到了,Client 和 Server 使用的 SRTP 加密參數(shù):master_key 和 master_salt.
DTLS 是基于 UDP 的,不可避免會(huì)出現(xiàn)丟包,需要重傳。如果處理不當(dāng),會(huì)導(dǎo)致整個(gè)通信雙方無(wú)法建立會(huì)話,通話失敗。RFC6347 4.2.4 給出了超時(shí)和重傳機(jī)制。 在處理重傳時(shí),以下幾點(diǎn)需要注意:
在 DTLS 協(xié)議中,為了解決丟包和重傳問(wèn)題,新增了 message_seq. 在發(fā)送 DTLS 重傳消息時(shí),一定要更新其中的 message_seq
,這樣對(duì)端將把包識(shí)別是一個(gè)重傳包,響應(yīng)正確消息。否則,會(huì)默默丟棄這些包,不進(jìn)行響應(yīng)。
當(dāng) server 端收到 client 的 FINISHED 消息,并發(fā)送 FINISHED 消息給 client,更新 server 狀態(tài)為協(xié)商完成,開(kāi)始發(fā)送 SRTP 數(shù)據(jù)。此時(shí)發(fā)送給 client 的 FINISHED 消息,出現(xiàn)丟包。client 收到 SRTP 數(shù)據(jù)后丟棄。同時(shí),再次發(fā)送 FINISHED 消息到 server,server 要正確響應(yīng)。否則,會(huì)導(dǎo)致 DTLS 協(xié)商完成的假象,通話失敗。
使用 openssl 1.1.1 之前版本,無(wú)法設(shè)置 DTLS 超時(shí)重傳時(shí)間,可以超時(shí)重傳機(jī)制不可用,大家開(kāi)始轉(zhuǎn)向使用 boringssl。openssl 1.1.1 開(kāi)始版本已經(jīng)支持設(shè)置 DTLS 超時(shí)重傳,達(dá)到和 boringssl 同樣的效果。參考 DTLS_set_timer_cb
DTLS 是一個(gè)龐大的協(xié)議體系,其中包括了各種加密,簽名,證書(shū),壓縮等多種算法。大多數(shù)項(xiàng)目是基于 OpenSSL 或 BoringSSL 實(shí)現(xiàn)的 DTLS 功能。在實(shí)際項(xiàng)目使用 OpenSSL 的 DTLS 功能,與協(xié)商有關(guān)的接口總結(jié)如下。
X509_digest,計(jì)算證書(shū) fingerprint,用在 SDP 協(xié)商中的 fingerprint
屬性。
SSL_CTX_set_cipher_list,設(shè)置使用的加密套件,通過(guò)設(shè)置算法的描述,影響 Hello 消息中的 cipher list。
SSL_CTX_set1_sigalgs_list 設(shè)置簽名算法。通過(guò)設(shè)置簽名算法的描述,影響 hello 消息中 signature_algorithms
擴(kuò)展。signature_algorithms
對(duì) DTLS 的 Hello 消息
,KeyExchange
,CerficateVerify
消息。signature_algorithms
設(shè)置不正確,會(huì)出現(xiàn) internal error,不容易定位問(wèn)題。
SSL_CTX_set_verify 設(shè)置是否校驗(yàn)對(duì)端的證書(shū)。由于在 RTC 中大多數(shù)據(jù)情況下使用自簽證書(shū),所以對(duì)證書(shū)的校驗(yàn),已校驗(yàn)身份是需要的。
SSL_CTX_set_tlsext_use_srtp 設(shè)置 srtp
擴(kuò)展。srtp 擴(kuò)展中的 profile,影響 srtp 加密時(shí)使用密鑰的協(xié)商和提取。
SSL_set_options 使用 SSL_OP_NO_QUERY_MTU
和 [SSL_set_mtu] 設(shè)置 fragment 的大小。默認(rèn) OpenSSL 使用 fragment 較小。通過(guò)上面兩個(gè)接口,設(shè)置適合網(wǎng)絡(luò)情況的 fragment。
DTLS_set_timer_cb,設(shè)置超時(shí)重傳的 Callback,由 callback 設(shè)置更合理的超時(shí)重傳時(shí)間。
在開(kāi)源項(xiàng)目 SRS 中已經(jīng)支持了 WebRTC 的基礎(chǔ)協(xié)議,對(duì) DTLS 協(xié)議感興趣的同學(xué),可以基于 SRS 快速搭建本機(jī)環(huán)境,通過(guò)調(diào)試,進(jìn)一步加深對(duì) DTLS 的理解。
感謝各位的閱讀,以上就是“什么是DTLS協(xié)議”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)什么是DTLS協(xié)議這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。