作者|进学
审校|泰一
DTLS (Datagram Transport Layer Security) 基于 UDP 场景下数据包可能失落或从新排序的现实情况下,为 UDP 定制和改良的 TLS 协定。在 WebRTC 中应用 DTLS 的中央包含两局部:协商和治理 [SRTP]() 密钥和为 [DataChannel]() 提供加密通道。
本文结合实际数据包剖析 WebRTC 应用 DTLS 进行 SRTP 密钥协商的流程。并对在理论我的项目中应用 DTLS 遇到的问题进行总结。
DTLS 协定简介
在剖析 DTLS 在 WebRTC 中的利用之前,先介绍下 DTLS 协定的基本原理。DTLS 协定由两层组成: Record 协定 和 Handshake 协定
- Record 协定:应用对称密钥对传输数据进行加密,并应用 HMAC 对数据进行完整性校验,实现了数据的平安传输。
-
Handshake 协定:应用非对称加密算法,实现 Record 协定应用的对称密钥的协商。
HandShake
TLS 握手协定流程如下,参考 RFC5246
DTLS 握手协定流程如下,参考 RFC6347
TLS 和 DTLS 的握手过程基本上是统一的,差异以及特地阐明如下:
- DTLS 中 HelloVerifyRequest 是为避免 DoS 攻打减少的音讯。
- TLS 没有发送 CertificateRequest,这个也不是必须的,是反向验证即服务器验证客户端。
- DTLS 的 RecordLayer 新增了 SequenceNumber 和 Epoch,以及 ClientHello 中新增了 Cookie,以及 Handshake 中新增了 Fragment 信息(避免超过 UDP 的 MTU),都是为了适应 UDP 的丢包以及容易被攻打做的改良。参考 RFC 6347
- DTLS 最初的 Alert 是将客户端的 Encrypted Alert 音讯,解密之后间接响应给客户端的,实际上 Server 应该回应加密的音讯,这里咱们的服务器回应明文是为了解析客户端加密的那个 Alert 包是什么。
RecordLayer 协定是和 DTLS 传输相干的协定,UDP 之上是 RecordLayer,RecordLayer 之上是 Handshake 或 ChangeCipherSpec 或 ApplicationData。RecordLayer 协定定义参考 RFC4347,实际上有三种 RecordLayer 的包:
DTLSPlaintext
,DTLS 明文的 RecordLayer。DTLSCompressed
,压缩的数据,个别不必。DTLSCiphertext
,加密的数据,在 ChangeCipherSpec 之后就是这种了。
没有明确的字段阐明是哪种音讯,不过能够依据上下文以及内容判断。比方 ChangeCipherSpec 是能够通过类型,它必定是一个 Plaintext。除了 Finished 的其余握手,个别都是 Plaintext。
SRTP 密钥协商
角色协商
在 DTLS 协定,通信的单方有 Client
和 Server
之分。在 WebRTC 中 DTLS 协商的身份是在 SDP
中形容的。形容如下,参考 SDP-Anatomy 中 DTLS 参数
a=setup:active
setup
属性在 RFC4145,
setup:active,作为 client,被动发动协商
setup:passive, 作为 sever,期待发动协商
setup:actpass, 作为 client,被动发动协商。作为 server,期待发动协商。
算法协商 – Hello 音讯
ClienHello 和 ServerHello 协商 DTLS 的 Version、CipherSuites、Random、以及 Extensions。
Version
:Client 给出本人能反对的、或者要应用的最高版本,比方 DTLS1.2。Server 收到这个信息后,依据本人能反对的、或者要应用的版本回应,比方 DTLS1.0。最终以协商的版本也就是 DTLS1.0 为准。CipherSuites
:Client 给出本人能反对的加密套件 CipherSuites,Server 收到后抉择本人能反对的回应一个,比方 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014),加密套件确定了证书的类型、密钥生成算法、摘要算法等。Random
:单方的随机数,参加到生成 MasterSecret。MasterSecret 会用来生成主密钥,导出 SRTP 密钥。详见 [导出 SRTP 密钥]-
Extensions
:Client 给出本人要应用的扩大协定,Server 能够回应本人反对的。比方 Client 尽管设置了 SessionTicket TLS 这个扩大,然而 Server 没有回应,所以最终并不会应用这个扩大。Cipher Suite
在 Hello 音讯中加密套接字应用 IANA
中的注册的名字。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 名字的同时,也能够查到在 OpenSSL 中的名字。TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 在 OpenSSL 中的名字为 ECDHE-RSA-AES128-GCM-SHA256
Note: 对于 Authentication (认证)、KeyExchange (密钥替换)、Encryption (加密)、MAC (Message Authentication Code) 音讯摘要等,能够参考 RSA 密钥协商。Extension
DTLS 的扩大协定,是在 ClientHello 和 ServerHello 的 Extensions 信息中指定的,所有的 TLS 扩大参考 TLS Extensions。上面列出几个 WebRTC 用到的扩大:
use_srtp
: DTLS 握手实现后 (Finished),应用 SRTP 传输数据,DTLS 生成 SRTP 的密钥。RFC5764。ClientHello 中的扩大信息定义了 RFC5764 4.1.2. SRTP Protection Profiles 和 srtp_mki。supported_groups
,原来的名字为 elliptic_curves,形容反对的 ECC 加密算法,参考 RFC8422 5.1.1.Supported Elliptic Curves Extension,个别用的是 secp256r1。signature_algorithms
,DTLS1.2 的扩大,指定应用的 Hash 和 Signature 算法,参考 RFC5246 7.4.1.4.1. Signature Algorithms。DTLS1.0,RSA 用的是 md5sha1 摘要算法,DSA 用的是 sha1 摘要算法。extended_master_secret
,扩大 MasterSecret 的生成形式,参考 RFC7627。在 KeyExchange 中,会退出一些常量来生成 MasterSecret。TLS 定义了扩大形式,如果用这个扩大,DTLS 的形式和 TLS 会有些不同。renegotiation_info
, 参考 RFC5746
除了这些扩大协定,和 SRTP 密钥导出相干的还有:
RFC5705: Keying Material Exporters for Transport Layer Security (TLS),DTLS 如何从 MasterSecret 导出 Key,比方 SRTP 的 Key。
RFC5764: DTLS Extension to Establish Keys for the SRTP,DTLS 的 use_srtp 扩大的具体标准,包含 ClientHello 扩大定义、Profile 定义、Key 的计算。
身份验证 – Certificate
数字证书是由一些公认可信的证书颁发机构签发的,不易伪造。数字证书能够用于接收者验证对端的身份,接收者收到某个对端的证书时,会对签名颁发机构的数字签名进行查看,一般来说,接收者当时就会事后装置很多罕用的签名颁发机构的证书(含有公开密钥),利用事后的公开密钥能够对签名进行验证。
Server 端通过 Hello 音讯,协商替换密钥的办法后,将 Server 证书发送给 Client,用于 Client 对 Server 的身份进行校验。Server 发送的证书必须实用于协商的 KeyExchange 应用的加密套接字,以及 Hello 音讯扩大中形容的 Hash/Signature 算法对。
在 WebRTC 中,通信的单方通常将无奈取得由出名根证书颁发机构 (CA) 签名的身份验证证书,自签名证书通常是惟一的抉择。RFC4572 定义一种机制,通过在 SDP
中减少自签名证书的平安哈希,称为 “ 证书指纹 ”,在保障 SDP 平安传输的前提下,如果提供的证书的指纹与 SDP
中的指纹匹配,则能够信赖自签名证书。在理论的利用场景中,SDP 在平安的信令通道 (https) 实现替换的,SDP 的平安残缺是能够做到的。这样在 DTLS 协商过程中,能够应用证书的指纹,实现通信单方的身份校验。证书指纹在 SDP 中的形容如下,参考 SDP-Anatomy 中 DTLS 参数
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
密钥替换 – KeyExchange
ServerKeyExchange 用来将 Server 端应用的公钥,发送给 Client 端。分为两种状况:
RSA
算法:如果服务端应用的是 RSA 算法,能够不发送这个音讯,因为 RSA 算法应用的公钥曾经在 Certificate 中形容。DH
算法,是依据对方的公钥和本人私钥计算共享密钥。因为 Client 和 Server 都只晓得本人的私钥,和对方的公钥;而他们的私钥都不同,依据非凡的数学个性,他们能计算出同样的共享密钥。对于 DH 算法如何计算出共享密钥,参考 DH 算法。
ClientKeyExchange 用来将 Client 应用的公钥,发送给 Server 端。
RSA
算法:如果密钥协商应用的 RSA 算法,发送应用 server 端 RSA 公钥,对 premaster secret 加密发送给 server 端。-
DH
算法:如果密钥协商应用的 DH 算法,并且在证书中没有形容,在将客户端应用的 DH 算法公钥发送给 Server 端,以便计算出共享密钥。
KeyExchange 的后果是,Client 和 Server 获取到了 RSA Key,或通过 DH 算法计算出共享密钥。详见 [导出 SRTP 密钥] 的过程证书验证 – CertificateVerify
应用 ClientRequest 中形容的 Hash/Signature 算法,对收到和发送的 HandShake 音讯签名发送个 Server。Server 端对签名进行校验。
加密验证 – Finished
当 Server 和 Client 实现对称密钥的替换后,通过 ChangeCipherSpec
告诉对端进入加密阶段,epoch 加 1。
随后 Client 应用替换的密钥,对 “client finished” 加密,应用 Finished 音讯,发送给服务端。Server 应用替换的密钥,对 “server finished” 进行加密发送给客户端。一旦验证了 finished 音讯后,就能够失常通信了。
导出 SRTP 密钥
下面介绍了 DTLS 的过程,以下通过联合下面例子给出的理论数据,具体阐明 SRTP 密钥的导出步骤。
协商后的加密算法
加密套件:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
椭圆曲线算法为:secp256r1,椭圆曲线的点压缩算法为:uncompressed。
椭圆曲线算法的基础知识的介绍在 ECC 椭圆曲线加密算法 – ECDH,ECDHE,ECDSA,由文档中咱们能够晓得,确定椭圆曲线加密算法有如下参数:
- 素数 p,用于确定无限域的范畴
- 椭圆曲线方程中的 a,b 参数
- 用于生成子群的的基点 G
- 子群的阶 n
- 子群的辅助因子 h
定义为六元组(p,a,b,G,n,h)
通过在 SECG-SEC2 2.4.2 Recommended Parameters secp256r1 中能够查到 secp256r1 对应的参数如下:
secp256r1 应用的参数如下:应用的素数 p:
p=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF
=2224(232−1)+2192+296−1
椭圆曲线 E:y^2=x^3+ax+ b 的参数定义如下:a=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC
b=5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B
基点 G 的非压缩格局:G=046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5
无限域的阶 n:
n=FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551
辅助因子 h:
h=01
通过 KeyExchange 替换椭圆曲线算法公钥
ECDH Server Parameter
Pubkey:04b0ce3c5f2c4a9fbe7c2257c1328438f3378f74e9f528b6e27a00b44eee4c19e5e6b2cb6cab09f796bcf8c05102b2a4bcdc753d91cc4f431f558c845a1ba6f1ce
记为 Spk
ECDH Client Paramter
PubKey: 0454e8fbef1503109d619c39be0ccaf89efa3c3962300476465cbc66b15152cd8a900c45d506420f0123e65d8fbb70cb60b497893f81c5c2a0ef2f4bc2da996d9e
记为 Cpk
依据 ECDHE 算法计算共享密钥 S(pre-master-secret)
假如 Server 的应用的椭圆曲线私钥为 Ds, Client 应用的 Dc,计算共享密钥的如下,参考 ECC 椭圆曲线加密算法 – ECDH,ECDHE,ECDSA
S = Ds Cpk = Dc Spk
这个共享密钥 S
就是咱们在 RFC 文档中看到的 pre-master-secret
计算 master secret
计算 master secret
过程如下,可参考 Computing the Master Secret
master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random)[0..47];
计算出来的 master_secret
为 48 Bytes,其中 ClientHello.random
和 ServerHello.random
在 Hello 音讯中给出。PRF
是伪随机数函数 (pseudorandom function),在协商的加密套件中给出。
应用 master_secrete 导出 SRTP 加密参数字节序列
应用 RFC5705 4. Exporter Definition 给出的计算形式,应用参数 master_secret
,client_random
,server_random
计算字节序列:
key_block = PRF(master_secret, "EXTRACTOR-dtls_srtp", client_random + server_random)[length]
在 DTLS-SRTP 4.2. Key Derivation 中形容了须要的字节序列长度。
2 * (SRTPSecurityParams.master_key_len + SRTPSecurityParams.master_salt_len) bytes of data
master_key_len 和 master_salt_len 的值,在 user_srtp
形容的 profile 中定义。咱们的实例中应用的 profile 为 SRTP_AES128_CM_HMAC_SHA1_80
,对应的 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
字节序列。
导出 SRTP 密钥
计算出 SRTP 加密参数字节序列,在 DTLS-SRTP 4.2. Key Derivation 形容了字节序列的含意:
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 加密参数:master_key 和 master_salt.
DTLS 超时重传
DTLS 是基于 UDP 的,不可避免会呈现丢包,须要重传。如果处理不当,会导致整个通信单方无奈建设会话,通话失败。RFC6347 4.2.4 给出了超时和重传机制。
在解决重传时,以下几点须要留神:
- 在 DTLS 协定中,为了解决丢包和重传问题,新增了 message_seq. 在发送 DTLS 重传音讯时,肯定要更新其中的
message_seq
,这样对端将把包辨认是一个重传包,响应正确音讯。否则,会默默抛弃这些包,不进行响应。 - 当 server 端收到 client 的 FINISHED 音讯,并发送 FINISHED 音讯给 client,更新 server 状态为协商实现,开始发送 SRTP 数据。此时发送给 client 的 FINISHED 音讯,呈现丢包。client 收到 SRTP 数据后抛弃。同时,再次发送 FINISHED 音讯到 server,server 要正确响应。否则,会导致 DTLS 协商实现的假象,通话失败。
-
应用 openssl 1.1.1 之前版本,无奈设置 DTLS 超时重传工夫,能够超时重传机制不可用,大家开始转向应用 boringssl。openssl 1.1.1 开始版本曾经反对设置 DTLS 超时重传,达到和 boringssl 同样的成果。参考 DTLS_set_timer_cb
OpenSSL 的 DTLS 性能
DTLS 是一个宏大的协定体系,其中包含了各种加密,签名,证书,压缩等多种算法。大多数我的项目是基于 OpenSSL 或 BoringSSL 实现的 DTLS 性能。在理论我的项目应用 OpenSSL 的 DTLS 性能,与协商无关的接口总结如下。
- X509_digest,计算证书 fingerprint,用在 SDP 协商中的
fingerprint
属性。 - SSL_CTX_set_cipher_list,设置应用的加密套件,通过设置算法的形容,影响 Hello 音讯中的 cipher list。
- SSL_CTX_set1_sigalgs_list 设置签名算法。通过设置签名算法的形容,影响 hello 音讯中
signature_algorithms
扩大。signature_algorithms
对 DTLS 的Hello 音讯
,KeyExchange
,CerficateVerify
音讯。signature_algorithms
设置不正确,会呈现 internal error,不容易定位问题。 - SSL_CTX_set_verify 设置是否校验对端的证书。因为在 RTC 中大多数据状况下应用自签证书,所以对证书的校验,已校验身份是须要的。
- SSL_CTX_set_tlsext_use_srtp 设置
srtp
扩大。srtp 扩大中的 profile,影响 srtp 加密时应用密钥的协商和提取。 - SSL_set_options 应用
SSL_OP_NO_QUERY_MTU
和 [SSL_set_mtu] 设置 fragment 的大小。默认 OpenSSL 应用 fragment 较小。通过下面两个接口,设置适宜网络状况的 fragment。 - DTLS_set_timer_cb,设置超时重传的 Callback,由 callback 设置更正当的超时重传工夫。
在开源我的项目 SRS 中曾经反对了 WebRTC 的根底协定,对 DTLS 协定感兴趣的同学,能够基于 SRS 疾速搭建本机环境,通过调试,进一步加深对 DTLS 的了解。
总结
本文通过 WebRTC 中 SRTP 密钥的协商过程,来阐明 DTLS 在 WebRTC 中的利用。DTLS 协定设计的各个加密算法的常识较多,加上 TLS 音讯的在各种利用场景中的扩大,不免有了解和认知不到的中央,还须要进一步深刻摸索。
参考文献
- TLS 1.2
- DTLS 1.2
- TLS Session Hash Extension
- TCP-Based Media Transport in the Session Description Protocol
- TLS Extension
- SRTP Extension for DTLS
- OpenSSL Man
- ECC 椭圆曲线加密算法 – 介绍
- ECC 椭圆曲线加密算法 – 无限域和离散对数
- ECC 椭圆曲线加密算法 – ECDH、ECDHE 和 ECDSA
「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实际技术文章,在这里与音视频畛域一流工程师交换切磋。公众号后盾回复【技术】可退出阿里云视频云技术交换群,和作者一起探讨音视频技术,获取更多行业最新信息。