乐趣区

关于webrtc:详解-WebRTC-传输安全机制一文读懂-DTLS-协议

作者|进学

审校|泰一

DTLS (Datagram Transport Layer Security) 基于 UDP 场景下数据包可能失落或从新排序的现实情况下,为 UDP 定制和改良的 TLS 协定。在 WebRTC 中应用 DTLS 的中央包含两局部:协商和治理 [SRTP]() 密钥和为 [DataChannel]() 提供加密通道。

本文结合实际数据包剖析 WebRTC 应用 DTLS 进行 SRTP 密钥协商的流程。并对在理论我的项目中应用 DTLS 遇到的问题进行总结。

DTLS 协定简介

在剖析 DTLS 在 WebRTC 中的利用之前,先介绍下 DTLS 协定的基本原理。DTLS 协定由两层组成: Record 协定 和 Handshake 协定

  1. Record 协定:应用对称密钥对传输数据进行加密,并应用 HMAC 对数据进行完整性校验,实现了数据的平安传输。
  2. 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 协定,通信的单方有 ClientServer 之分。在 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 端。分为两种状况:

  1. RSA 算法:如果服务端应用的是 RSA 算法,能够不发送这个音讯,因为 RSA 算法应用的公钥曾经在 Certificate 中形容。
  2. DH 算法,是依据对方的公钥和本人私钥计算共享密钥。因为 Client 和 Server 都只晓得本人的私钥,和对方的公钥;而他们的私钥都不同,依据非凡的数学个性,他们能计算出同样的共享密钥。对于 DH 算法如何计算出共享密钥,参考 DH 算法。

ClientKeyExchange 用来将 Client 应用的公钥,发送给 Server 端。

  1. RSA 算法:如果密钥协商应用的 RSA 算法,发送应用 server 端 RSA 公钥,对 premaster secret 加密发送给 server 端。
  2. 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.randomServerHello.random 在 Hello 音讯中给出。PRF 是伪随机数函数 (pseudorandom function),在协商的加密套件中给出。

应用 master_secrete 导出 SRTP 加密参数字节序列

应用 RFC5705 4. Exporter Definition 给出的计算形式,应用参数 master_secretclient_randomserver_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 给出了超时和重传机制。
在解决重传时,以下几点须要留神:

  1. 在 DTLS 协定中,为了解决丢包和重传问题,新增了 message_seq. 在发送 DTLS 重传音讯时,肯定要更新其中的 message_seq,这样对端将把包辨认是一个重传包,响应正确音讯。否则,会默默抛弃这些包,不进行响应。
  2. 当 server 端收到 client 的 FINISHED 音讯,并发送 FINISHED 音讯给 client,更新 server 状态为协商实现,开始发送 SRTP 数据。此时发送给 client 的 FINISHED 音讯,呈现丢包。client 收到 SRTP 数据后抛弃。同时,再次发送 FINISHED 音讯到 server,server 要正确响应。否则,会导致 DTLS 协商实现的假象,通话失败。
  3. 应用 openssl 1.1.1 之前版本,无奈设置 DTLS 超时重传工夫,能够超时重传机制不可用,大家开始转向应用 boringssl。openssl 1.1.1 开始版本曾经反对设置 DTLS 超时重传,达到和 boringssl 同样的成果。参考 DTLS_set_timer_cb

    OpenSSL 的 DTLS 性能

    DTLS 是一个宏大的协定体系,其中包含了各种加密,签名,证书,压缩等多种算法。大多数我的项目是基于 OpenSSL 或 BoringSSL 实现的 DTLS 性能。在理论我的项目应用 OpenSSL 的 DTLS 性能,与协商无关的接口总结如下。

  4. X509_digest,计算证书 fingerprint,用在 SDP 协商中的 fingerprint 属性。
  5. SSL_CTX_set_cipher_list,设置应用的加密套件,通过设置算法的形容,影响 Hello 音讯中的 cipher list。
  6. SSL_CTX_set1_sigalgs_list 设置签名算法。通过设置签名算法的形容,影响 hello 音讯中 signature_algorithms 扩大。signature_algorithms 对 DTLS 的 Hello 音讯KeyExchangeCerficateVerify 音讯。signature_algorithms 设置不正确,会呈现 internal error,不容易定位问题。
  7. SSL_CTX_set_verify 设置是否校验对端的证书。因为在 RTC 中大多数据状况下应用自签证书,所以对证书的校验,已校验身份是须要的。
  8. SSL_CTX_set_tlsext_use_srtp 设置 srtp 扩大。srtp 扩大中的 profile,影响 srtp 加密时应用密钥的协商和提取。
  9. SSL_set_options 应用 SSL_OP_NO_QUERY_MTU 和 [SSL_set_mtu] 设置 fragment 的大小。默认 OpenSSL 应用 fragment 较小。通过下面两个接口,设置适宜网络状况的 fragment。
  10. DTLS_set_timer_cb,设置超时重传的 Callback,由 callback 设置更正当的超时重传工夫。

在开源我的项目 SRS 中曾经反对了 WebRTC 的根底协定,对 DTLS 协定感兴趣的同学,能够基于 SRS 疾速搭建本机环境,通过调试,进一步加深对 DTLS 的了解。

总结

本文通过 WebRTC 中 SRTP 密钥的协商过程,来阐明 DTLS 在 WebRTC 中的利用。DTLS 协定设计的各个加密算法的常识较多,加上 TLS 音讯的在各种利用场景中的扩大,不免有了解和认知不到的中央,还须要进一步深刻摸索。

参考文献

  1. TLS 1.2
  2. DTLS 1.2
  3. TLS Session Hash Extension
  4. TCP-Based Media Transport in the Session Description Protocol
  5. TLS Extension
  6. SRTP Extension for DTLS
  7. OpenSSL Man
  8. ECC 椭圆曲线加密算法 – 介绍
  9. ECC 椭圆曲线加密算法 – 无限域和离散对数
  10. ECC 椭圆曲线加密算法 – ECDH、ECDHE 和 ECDSA

「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实际技术文章,在这里与音视频畛域一流工程师交换切磋。公众号后盾回复【技术】可退出阿里云视频云技术交换群,和作者一起探讨音视频技术,获取更多行业最新信息。

退出移动版