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

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"作者|进学","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"审校|泰一","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DTLS (Datagram Transport Layer Security) 基于 UDP 场景下数据包可能丢失或重新排序的现实情况下,为 UDP 定制和改进的 TLS 协议。在 WebRTC 中使用 DTLS 的地方包括两部分:协商和管理 ","attrs":{}},{"type":"link","attrs":{"href":"","title":"","type":null},"content":[{"type":"text","text":"SRTP","attrs":{}}]},{"type":"text","text":" 密钥和为 ","attrs":{}},{"type":"link","attrs":{"href":"","title":"","type":null},"content":[{"type":"text","text":"DataChannel","attrs":{}}]},{"type":"text","text":" 提供加密通道。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/53/53e7d438332ef7a0432f28e943ef270b.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文结合实际数据包分析 WebRTC 使用 DTLS 进行 SRTP 密钥协商的流程。并对在实际项目中使用 DTLS 遇到的问题进行总结。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"DTLS 协议简介","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在分析 DTLS 在 WebRTC 中的应用之前,先介绍下 DTLS 协议的基本原理。DTLS 协议由两层组成: Record 协议 和 Handshake 协议","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"Record 协议:使用对称密钥对传输数据进行加密,并使用 HMAC 对数据进行完整性校验,实现了数据的安全传输。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"Handshake 协议:使用非对称加密算法,完成 Record 协议使用的对称密钥的协商。","attrs":{}}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"HandShake","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TLS 握手协议流程如下,参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5246?spm=a2c6h.12873639.0.0.4c9a21a8kxR03N#section-7.3","title":"","type":null},"content":[{"type":"text","text":"RFC5246","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/79/79aad8d4f872b627e92a68aa10a3570b.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DTLS 握手协议流程如下,参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc6347?spm=a2c6h.12873639.0.0.4c9a21a8kxR03N#section-4.2.4","title":"","type":null},"content":[{"type":"text","text":"RFC6347","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b7/b712f7706ccc18e3628459d6d509939a.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c5/c5477a5168b2f8dea96064d865599dea.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TLS 和 DTLS 的握手过程基本上是一致的,差别以及特别说明如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DTLS 中 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc6347","title":"","type":null},"content":[{"type":"text","text":"HelloVerifyRequest","attrs":{}}]},{"type":"text","text":" 是为防止 DoS 攻击增加的消息。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"TLS 没有发送 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5246#section-7.4.4","title":"","type":null},"content":[{"type":"text","text":"CertificateRequest","attrs":{}}]},{"type":"text","text":",这个也不是必须的,是反向验证即服务器验证客户端。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DTLS 的 RecordLayer 新增了 SequenceNumber 和 Epoch,以及 ClientHello 中新增了 Cookie,以及 Handshake 中新增了 Fragment 信息(防止超过 UDP 的 MTU),都是为了适应 UDP 的丢包以及容易被攻击做的改进。参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc6347#section-4.2.2","title":"","type":null},"content":[{"type":"text","text":"RFC 6347","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DTLS 最后的 Alert 是将客户端的 Encrypted Alert 消息,解密之后直接响应给客户端的,实际上 Server 应该回应加密的消息,这里我们的服务器回应明文是为了解析客户端加密的那个 Alert 包是什么。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"RecordLayer 协议是和 DTLS 传输相关的协议,UDP 之上是 RecordLayer,RecordLayer 之上是 Handshake 或 ChangeCipherSpec 或 ApplicationData。RecordLayer 协议定义参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc4347","title":"","type":null},"content":[{"type":"text","text":"RFC4347","attrs":{}}]},{"type":"text","text":",实际上有三种 RecordLayer 的包:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"DTLSPlaintext","attrs":{}}],"attrs":{}},{"type":"text","text":",DTLS 明文的 RecordLayer。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"DTLSCompressed","attrs":{}}],"attrs":{}},{"type":"text","text":",压缩的数据,一般不用。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"DTLSCiphertext","attrs":{}}],"attrs":{}},{"type":"text","text":",加密的数据,在 ChangeCipherSpec 之后就是这种了。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"没有明确的字段说明是哪种消息,不过可以根据上下文以及内容判断。比如 ChangeCipherSpec 是可以通过类型,它肯定是一个 Plaintext。除了 Finished 的其他握手,一般都是 Plaintext。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"SRTP 密钥协商","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"角色协商","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 DTLS 协议,通信的双方有 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Client","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Server","attrs":{}}],"attrs":{}},{"type":"text","text":" 之分。在 WebRTC 中 DTLS 协商的身份是在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SDP","attrs":{}}],"attrs":{}},{"type":"text","text":" 中描述的。描述如下,参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://webrtchacks.com/sdp-anatomy/","title":"","type":null},"content":[{"type":"text","text":"SDP-Anatomy","attrs":{}}]},{"type":"text","text":" 中 DTLS 参数","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"a=setup:active","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"setup","attrs":{}}],"attrs":{}},{"type":"text","text":" 属性在 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc4145#section-4.1","title":"","type":null},"content":[{"type":"text","text":"RFC4145","attrs":{}}]},{"type":"text","text":",","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"setup:active,作为 client,主动发起协商","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"setup:passive, 作为 sever,等待发起协商","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"setup:actpass, 作为 client,主动发起协商。作为 server,等待发起协商。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"算法协商 - Hello 消息","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ClienHello 和 ServerHello 协商 DTLS 的 Version、CipherSuites、Random、以及 Extensions。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8b/8b5e5dbadbcbd9d2e876fc7f39973da6.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/27/274c57b90bc0bd9960818c717330ebaf.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Version","attrs":{}}],"attrs":{}},{"type":"text","text":":Client 给出自己能支持的、或者要使用的最高版本,比如 DTLS1.2。Server 收到这个信息后,根据自己能支持的、或者要使用的版本回应,比如 DTLS1.0。最终以协商的版本也就是 DTLS1.0 为准。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"CipherSuites","attrs":{}}],"attrs":{}},{"type":"text","text":":Client 给出自己能支持的加密套件 CipherSuites,Server 收到后选择自己能支持的回应一个,比如 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014),加密套件确定了证书的类型、密钥生成算法、摘要算法等。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Random","attrs":{}}],"attrs":{}},{"type":"text","text":":双方的随机数,参与到生成 MasterSecret。MasterSecret 会用来生成主密钥,导出 SRTP 密钥。详见 [导出 SRTP 密钥]","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Extensions","attrs":{}}],"attrs":{}},{"type":"text","text":":Client 给出自己要使用的扩展协议,Server 可以回应自己支持的。比如 Client 虽然设置了 SessionTicket TLS 这个扩展,但是 Server 没有回应,所以最终并不会使用这个扩展。","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Cipher Suite","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3a/3ae8b9e98084e0bfa5b5d284f0ea2064.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 Hello 消息中加密套接字使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"IANA","attrs":{}}],"attrs":{}},{"type":"text","text":" 中的注册的名字。IANA 名字由 Protocol,Key Exchange Algorithm,Authentication Algorithm,Encryption Algorithm ,Hash Algorithm 的描述组成。例如,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 的含义如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Protocol","attrs":{}}],"attrs":{}},{"type":"text","text":": Transport Layer Security (TLS)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Key Exchange","attrs":{}}],"attrs":{}},{"type":"text","text":": Elliptic Curve Diffie-Hellman Ephemeral (ECDHE)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Authentication","attrs":{}}],"attrs":{}},{"type":"text","text":": Rivest Shamir Adleman algorithm (RSA)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Encryption","attrs":{}}],"attrs":{}},{"type":"text","text":": Advanced Encryption Standard with 128bit key in Galois/Counter mode (AES 128 GCM)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"Hash","attrs":{}}],"attrs":{}},{"type":"text","text":": Secure Hash Algorithm 256 (SHA256)","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"加密套接字在 ","attrs":{}},{"type":"link","attrs":{"href":"https://ciphersuite.info/cs/","title":"","type":null},"content":[{"type":"text","text":"ciphersuite.info","attrs":{}}]},{"type":"text","text":" 可以查到。在查到 IANA 名字的同时,也可以查到在 OpenSSL 中的名字。TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 在 OpenSSL 中的名字为 ECDHE-RSA-AES128-GCM-SHA256Note: 关于 Authentication (认证)、KeyExchange (密钥交换)、Encryption (加密)、MAC (Message Authentication Code) 消息摘要等,可以参考","attrs":{}},{"type":"link","attrs":{"href":"https://www.zhihu.com/question/25116415","title":"","type":null},"content":[{"type":"text","text":" RSA 密钥协商","attrs":{}}]},{"type":"text","text":"。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Extension","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DTLS 的扩展协议,是在 ClientHello 和 ServerHello 的 Extensions 信息中指定的,所有的 TLS 扩展参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml","title":"","type":null},"content":[{"type":"text","text":"TLS Extensions","attrs":{}}]},{"type":"text","text":"。下面列出几个 WebRTC 用到的扩展:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"use_srtp","attrs":{}}],"attrs":{}},{"type":"text","text":": DTLS 握手完成后 (Finished),使用 SRTP 传输数据,DTLS 生成 SRTP 的密钥。 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5764","title":"","type":null},"content":[{"type":"text","text":"RFC5764","attrs":{}}]},{"type":"text","text":"。ClientHello 中的扩展信息定义了 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5764#page-8","title":"","type":null},"content":[{"type":"text","text":"RFC5764 4.1.2. SRTP Protection Profiles","attrs":{}}]},{"type":"text","text":" 和 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5764#section-4.1.3","title":"","type":null},"content":[{"type":"text","text":"srtp_mki","attrs":{}}]},{"type":"text","text":"。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":"none"},"content":[{"type":"image","attrs":{"src":"https://intranetproxy.alipay.com/skylark/lark/0/2021/png/166666/1618149732986-7902bd92-d4f4-4dc1-913d-3491d4243cdb.png?x-oss-process=image%2Fresize%2Cw_694","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"supported_groups","attrs":{}}],"attrs":{}},{"type":"text","text":",原来的名字为 elliptic_curves,描述支持的 ECC 加密算法,参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc8422#section-5.1.1","title":"","type":null},"content":[{"type":"text","text":"RFC8422 5.1.1.Supported Elliptic Curves Extension","attrs":{}}]},{"type":"text","text":",一般用的是 secp256r1。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":"none"},"content":[{"type":"image","attrs":{"src":"https://intranetproxy.alipay.com/skylark/lark/0/2021/png/166666/1618149817717-a840a0ed-dc79-41f7-99c0-cff1b8d09284.png?x-oss-process=image%2Fresize%2Cw_694","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"signature_algorithms","attrs":{}}],"attrs":{}},{"type":"text","text":",DTLS1.2 的扩展,指定使用的 Hash 和 Signature 算法,参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1","title":"","type":null},"content":[{"type":"text","text":"RFC5246 7.4.1.4.1. Signature Algorithms","attrs":{}}]},{"type":"text","text":"。DTLS1.0,RSA 用的是 md5sha1 摘要算法,DSA 用的是 sha1 摘要算法。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":"none"},"content":[{"type":"image","attrs":{"src":"https://intranetproxy.alipay.com/skylark/lark/0/2021/png/166666/1618149874234-54bf92cc-87ff-48e5-a02e-910576989a64.png?x-oss-process=image%2Fresize%2Cw_694","alt":null,"title":null,"style":null,"href":null,"fromPaste":false,"pastePass":false}}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"extended_master_secret","attrs":{}}],"attrs":{}},{"type":"text","text":",扩展 MasterSecret 的生成方式,参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc7627","title":"","type":null},"content":[{"type":"text","text":"RFC7627","attrs":{}}]},{"type":"text","text":"。在 KeyExchange 中,会加入一些常量来生成 MasterSecret。TLS 定义了扩展方式,如果用这个扩展,DTLS 的方式和 TLS 会有些不同。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"renegotiation_info","attrs":{}}],"attrs":{}},{"type":"text","text":", 参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5746#section-3.2","title":"","type":null},"content":[{"type":"text","text":"RFC5746","attrs":{}}]}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了这些扩展协议,和 SRTP 密钥导出相关的还有:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"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 的计算。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"身份验证 - Certificate","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/01/0171be1632396a50bb9f9ac8e75a22b2.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"数字证书是由一些公认可信的证书颁发机构签发的,不易伪造。数字证书可以用于接收者验证对端的身份,接收者收到某个对端的证书时,会对签名颁发机构的数字签名进行检查,一般来说,接收者事先就会预先安装很多常用的签名颁发机构的证书(含有公开密钥),利用预先的公开密钥可以对签名进行验证。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Server 端通过 Hello 消息,协商交换密钥的方法后,将 Server 证书发送给 Client,用于 Client 对 Server 的身份进行校验。Server 发送的证书必须适用于协商的 KeyExchange 使用的加密套接字,以及 Hello 消息扩展中描述的 Hash/Signature 算法对。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 WebRTC 中,通信的双方通常将无法获得由知名根证书颁发机构 (CA) 签名的身份验证证书,自签名证书通常是唯一的选择。","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc4572","title":"","type":null},"content":[{"type":"text","text":"RFC4572","attrs":{}}]},{"type":"text","text":" 定义一种机制,通过在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SDP","attrs":{}}],"attrs":{}},{"type":"text","text":" 中增加自签名证书的安全哈希,称为 \"证书指纹\",在保证 SDP 安全传输的前提下,如果提供的证书的指纹与 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SDP","attrs":{}}],"attrs":{}},{"type":"text","text":" 中的指纹匹配,则可以信任自签名证书。在实际的应用场景中,SDP 在安全的信令通道 (https) 完成交换的,SDP 的安全完整是可以做到的。这样在 DTLS 协商过程中,可以使用证书的指纹,完成通信双方的身份校验。证书指纹在 SDP 中的描述如下,参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://webrtchacks.com/sdp-anatomy/","title":"","type":null},"content":[{"type":"text","text":"SDP-Anatomy","attrs":{}}]},{"type":"text","text":" 中 DTLS 参数","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"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","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"密钥交换 - KeyExchange","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ServerKeyExchange 用来将 Server 端使用的公钥,发送给 Client 端。分为两种情况:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"RSA","attrs":{}}],"attrs":{}},{"type":"text","text":" 算法:如果服务端使用的是 RSA 算法,可以不发送这个消息,因为 RSA 算法使用的公钥已经在 Certificate 中描述。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"DH","attrs":{}}],"attrs":{}},{"type":"text","text":" 算法,是根据对方的公钥和自己私钥计算共享密钥。因为 Client 和 Server 都只知道自己的私钥,和对方的公钥;而他们的私钥都不同,根据特殊的数学特性,他们能计算出同样的共享密钥。关于 DH 算法如何计算出共享密钥,参考 ","attrs":{}},{"type":"link","attrs":{"href":"http://www.voidcn.com/article/p-rgubrwfd-bpg.html","title":"","type":null},"content":[{"type":"text","text":"DH 算法","attrs":{}}]},{"type":"text","text":"。","attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c8/c85d18e054ebb5ab3e35fa0baa213afd.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ClientKeyExchange 用来将 Client 使用的公钥,发送给 Server 端。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"RSA","attrs":{}}],"attrs":{}},{"type":"text","text":" 算法:如果密钥协商使用的 RSA 算法,发送使用 server 端 RSA 公钥,对 premaster secret 加密发送给 server 端。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"DH","attrs":{}}],"attrs":{}},{"type":"text","text":" 算法:如果密钥协商使用的 DH 算法,并且在证书中没有描述,在将客户端使用的 DH 算法公钥发送给 Server 端,以便计算出共享密钥。KeyExchange 的结果是,Client 和 Server 获取到了 RSA Key, 或通过 DH 算法计算出共享密钥。详见 [导出 SRTP 密钥] 的过程","attrs":{}}]}]}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"证书验证 - CertificateVerify","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用 ClientRequest 中描述的 Hash/Signature 算法,对收到和发送的 HandShake 消息签名发送个 Server。Server 端对签名进行校验。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/5f/5ffabb189a83c1c19b72f0fd44ebe84f.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"加密验证 - Finished","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"当 Server 和 Client 完成对称密钥的交换后,通过 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ChangeCipherSpec","attrs":{}}],"attrs":{}},{"type":"text","text":" 通知对端进入加密阶段,epoch 加 1。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"随后 Client 使用交换的密钥,对 \"client finished\" 加密,使用 Finished 消息,发送给服务端。Server 使用交换的密钥,对 \"server finished\" 进行加密发送给客户端。一旦验证了 finished 消息后,就可以正常通信了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e4/e43e056a9efafee909b1ca869a3f2045.png","alt":null,"title":null,"style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"导出 SRTP 密钥","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"上面介绍了 DTLS 的过程,以下通过结合上面例子给出的实际数据,详细说明 SRTP 密钥的导出步骤。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"协商后的加密算法","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"加密套件:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)椭圆曲线算法为:secp256r1,椭圆曲线的点压缩算法为:uncompressed。椭圆曲线算法的基础知识的介绍在 ","attrs":{}},{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/66794410","title":"","type":null},"content":[{"type":"text","text":"ECC 椭圆曲线加密算法 - ECDH,ECDHE,ECDSA","attrs":{}}]},{"type":"text","text":" ,由文档中我们可以知道,确定椭圆曲线加密算法有如下参数:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"素数 p,用于确定有限域的范围","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"椭圆曲线方程中的 a,b 参数","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用于生成子群的的基点 G","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"子群的阶 n","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"子群的辅助因子 h定义为","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"六元组(p,a,b,G,n,h)","attrs":{}}],"attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通过在 ","attrs":{}},{"type":"link","attrs":{"href":"http://www.secg.org/sec2-v2.pdf","title":"","type":null},"content":[{"type":"text","text":"SECG-SEC2 2.4.2 Recommended Parameters secp256r1","attrs":{}}]},{"type":"text","text":" 中可以查到 secp256r1 对应的参数如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"secp256r1使用的参数如下:\n使用的素数p:\np=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF\n=2224(232−1)+2192+296−1\n椭圆曲线E:y^2=x^3+ax+b的参数定义如下:\na=FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC\nb=5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B\n基点G的非压缩格式:\nG=046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5\n有限域的阶n:\nn=FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551\n辅助因子h:\nh=01\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"通过 KeyExchange 交换椭圆曲线算法公钥","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ECDH Server Parameter","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"Pubkey:04b0ce3c5f2c4a9fbe7c2257c1328438f3378f74e9f528b6e27a00b44eee4c19e5e6b2cb6cab09f796bcf8c05102b2a4bcdc753d91cc4f431f558c845a1ba6f1ce\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"记为 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Spk","attrs":{}}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ECDH Client Paramter","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"PubKey: 0454e8fbef1503109d619c39be0ccaf89efa3c3962300476465cbc66b15152cd8a900c45d506420f0123e65d8fbb70cb60b497893f81c5c2a0ef2f4bc2da996d9e\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"记为 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Cpk","attrs":{}}],"attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"根据 ECDHE 算法计算共享密钥 S(pre-master-secret)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"假设 Server 的使用的椭圆曲线私钥为 Ds, Client 使用的 Dc,计算共享密钥的如下,参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/66794410","title":"","type":null},"content":[{"type":"text","text":"ECC 椭圆曲线加密算法 - ECDH,ECDHE,ECDSA","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"S = Ds * Cpk = Dc * Spk","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"这个共享密钥 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"S","attrs":{}}],"attrs":{}},{"type":"text","text":" 就是我们在 RFC 文档中看到的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"pre-master-secret","attrs":{}}],"attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"计算 master secret","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"计算 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"master secret","attrs":{}}],"attrs":{}},{"type":"text","text":" 过程如下,可参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5246#section-8.1","title":"","type":null},"content":[{"type":"text","text":"Computing the Master Secret","attrs":{}}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":" master_secret = PRF(pre_master_secret, \"master secret\", ClientHello.random + ServerHello.random)[0..47];\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"计算出来的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"master_secret","attrs":{}}],"attrs":{}},{"type":"text","text":" 为 48 Bytes,其中 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ClientHello.random","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"ServerHello.random","attrs":{}}],"attrs":{}},{"type":"text","text":" 在 Hello 消息中给出。","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"PRF","attrs":{}}],"attrs":{}},{"type":"text","text":" 是伪随机数函数 (pseudorandom function),在协商的加密套件中给出。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"使用 master_secrete 导出 SRTP 加密参数字节序列","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5705#section-4","title":"","type":null},"content":[{"type":"text","text":"RFC5705 4. Exporter Definition","attrs":{}}]},{"type":"text","text":" 给出的计算方式,使用参数 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"master_secret","attrs":{}}],"attrs":{}},{"type":"text","text":", ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"client_random","attrs":{}}],"attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"server_random","attrs":{}}],"attrs":{}},{"type":"text","text":" 计算字节序列:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"key_block = PRF(master_secret, \"EXTRACTOR-dtls_srtp\", client_random + server_random)[length]\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5764#section-4.2","title":"","type":null},"content":[{"type":"text","text":" DTLS-SRTP 4.2. Key Derivation","attrs":{}}]},{"type":"text","text":" 中描述了需要的字节序列长度。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"2 * (SRTPSecurityParams.master_key_len + SRTPSecurityParams.master_salt_len) bytes of data\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"master_key_len 和 master_salt_len 的值,在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"user_srtp","attrs":{}}],"attrs":{}},{"type":"text","text":" 描述的 profile 中定义。我们的实例中使用的 profile 为 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP_AES128_CM_HMAC_SHA1_80","attrs":{}}],"attrs":{}},{"type":"text","text":",对应的 profile 配置为:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"SRTP_AES128_CM_HMAC_SHA1_80\n cipher: AES_128_CM\n cipher_key_length: 128\n cipher_salt_length: 112\n maximum_lifetime: 2^31\n auth_function: HMAC-SHA1\n auth_key_length: 160\n auth_tag_length: 80\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也就是我们需要 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"(128/8+112/8)*2 = 60 bytes","attrs":{}}],"attrs":{}},{"type":"text","text":" 字节序列。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"导出 SRTP 密钥","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"计算出 SRTP 加密参数字节序列,在 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5764#section-4.2","title":"","type":null},"content":[{"type":"text","text":"DTLS-SRTP 4.2. Key Derivation","attrs":{}}]},{"type":"text","text":" 描述了字节序列的含义:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"client_write_SRTP_master_key[SRTPSecurityParams.master_key_len]; // 128 bits\nserver_write_SRTP_master_key[SRTPSecurityParams.master_key_len]; // 128 bits\nclient_write_SRTP_master_salt[SRTPSecurityParams.master_salt_len]; // 112 bits\nserver_write_SRTP_master_salt[SRTPSecurityParams.master_salt_len]; // 112 bits\n","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"至此我们得到了,Client 和 Server 使用的 SRTP 加密参数:master_key 和 master_salt.","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"DTLS 超时重传","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DTLS 是基于 UDP 的,不可避免会出现丢包,需要重传。如果处理不当,会导致整个通信双方无法建立会话,通话失败。","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc6347#section-4.2.4","title":"","type":null},"content":[{"type":"text","text":"RFC6347 4.2.4","attrs":{}}]},{"type":"text","text":" 给出了超时和重传机制。在处理重传时,以下几点需要注意:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"在 DTLS 协议中,为了解决丢包和重传问题,新增了 ","attrs":{}},{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc6347#section-4.2.2","title":"","type":null},"content":[{"type":"text","text":"message_seq.","attrs":{}}]},{"type":"text","text":" 在发送 DTLS 重传消息时,一定要更新其中的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"message_seq","attrs":{}}],"attrs":{}},{"type":"text","text":",这样对端将把包识别是一个重传包,响应正确消息。否则,会默默丢弃这些包,不进行响应。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"当 server 端收到 client 的 FINISHED 消息,并发送 FINISHED 消息给 client,更新 server 状态为协商完成,开始发送 SRTP 数据。此时发送给 client 的 FINISHED 消息,出现丢包。client 收到 SRTP 数据后丢弃。同时,再次发送 FINISHED 消息到 server,server 要正确响应。否则,会导致 DTLS 协商完成的假象,通话失败。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"使用 openssl 1.1.1 之前版本,无法设置 DTLS 超时重传时间,可以超时重传机制不可用,大家开始转向使用 boringssl。openssl 1.1.1 开始版本已经支持设置 DTLS 超时重传,达到和 boringssl 同样的效果。参考 ","attrs":{}},{"type":"link","attrs":{"href":"https://www.openssl.org/docs/man1.1.1/man3/DTLS_set_timer_cb.html","title":"","type":null},"content":[{"type":"text","text":"DTLS_set_timer_cb","attrs":{}}]}]}]}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"OpenSSL 的 DTLS 功能","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"DTLS 是一个庞大的协议体系,其中包括了各种加密,签名,证书,压缩等多种算法。大多数项目是基于 OpenSSL 或 BoringSSL 实现的 DTLS 功能。在实际项目使用 OpenSSL 的 DTLS 功能,与协商有关的接口总结如下。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.openssl.org/docs/man1.1.0/man3/X509_digest.html","title":"","type":null},"content":[{"type":"text","text":"X509_digest","attrs":{}}]},{"type":"text","text":",计算证书 fingerprint,用在 SDP 协商中的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"fingerprint","attrs":{}}],"attrs":{}},{"type":"text","text":" 属性。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_cipher_list.html","title":"","type":null},"content":[{"type":"text","text":"SSL_CTX_set_cipher_list","attrs":{}}]},{"type":"text","text":",设置使用的加密套件,通过设置算法的描述,影响 Hello 消息中的 cipher list。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set1_sigalgs_list.html","title":"","type":null},"content":[{"type":"text","text":"SSL_CTX_set1_sigalgs_list","attrs":{}}]},{"type":"text","text":" 设置签名算法。通过设置签名算法的描述,影响 hello 消息中 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"signature_algorithms","attrs":{}}],"attrs":{}},{"type":"text","text":" 扩展。","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"signature_algorithms","attrs":{}}],"attrs":{}},{"type":"text","text":" 对 DTLS 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Hello 消息","attrs":{}}],"attrs":{}},{"type":"text","text":" ,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"KeyExchange","attrs":{}}],"attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"CerficateVerify","attrs":{}}],"attrs":{}},{"type":"text","text":" 消息。","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"signature_algorithms","attrs":{}}],"attrs":{}},{"type":"text","text":" 设置不正确,会出现 internal error,不容易定位问题。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html","title":"","type":null},"content":[{"type":"text","text":"SSL_CTX_set_verify","attrs":{}}]},{"type":"text","text":" 设置是否校验对端的证书。由于在 RTC 中大多数据情况下使用自签证书,所以对证书的校验,已校验身份是需要的。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_tlsext_use_srtp.html","title":"","type":null},"content":[{"type":"text","text":"SSL_CTX_set_tlsext_use_srtp","attrs":{}}]},{"type":"text","text":" 设置 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"srtp","attrs":{}}],"attrs":{}},{"type":"text","text":" 扩展。srtp 扩展中的 profile,影响 srtp 加密时使用密钥的协商和提取。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.openssl.org/docs/man1.1.0/man3/SSL_set_options.html","title":"","type":null},"content":[{"type":"text","text":"SSL_set_options","attrs":{}}]},{"type":"text","text":" 使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SSL_OP_NO_QUERY_MTU","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 [SSL_set_mtu] 设置 fragment 的大小。默认 OpenSSL 使用 fragment 较小。通过上面两个接口,设置适合网络情况的 fragment。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.openssl.org/docs/man1.1.1/man3/DTLS_set_timer_cb.html","title":"","type":null},"content":[{"type":"text","text":"DTLS_set_timer_cb","attrs":{}}]},{"type":"text","text":",设置超时重传的 Callback,由 callback 设置更合理的超时重传时间。","attrs":{}}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在开源项目 ","attrs":{}},{"type":"link","attrs":{"href":"https://github.com/ossrs/srs","title":"","type":null},"content":[{"type":"text","text":"SRS","attrs":{}}]},{"type":"text","text":" 中已经支持了 WebRTC 的基础协议,对 DTLS 协议感兴趣的同学,可以基于 SRS 快速搭建本机环境,通过调试,进一步加深对 DTLS 的理解。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"总结","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文通过 WebRTC 中 SRTP 密钥的协商过程,来说明 DTLS 在 WebRTC 中的应用。DTLS 协议设计的各个加密算法的知识较多,加上 TLS 消息的在各种应用场景中的扩展,难免有理解和认知不到的地方,还需要进一步深入探索。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"参考文献","attrs":{}}]},{"type":"numberedlist","attrs":{"start":1,"normalizeStart":1},"content":[{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5246","title":"","type":null},"content":[{"type":"text","text":"TLS 1.2","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc6347","title":"","type":null},"content":[{"type":"text","text":"DTLS 1.2","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc7627","title":"","type":null},"content":[{"type":"text","text":"TLS Session Hash Extension","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc4145","title":"","type":null},"content":[{"type":"text","text":"TCP-Based Media Transport in the Session Description Protocol","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":5,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml","title":"","type":null},"content":[{"type":"text","text":"TLS Extension","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":6,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://tools.ietf.org/html/rfc5764","title":"","type":null},"content":[{"type":"text","text":"SRTP Extension for DTLS ","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":7,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.openssl.org/docs/man1.1.1/man3","title":"","type":null},"content":[{"type":"text","text":"OpenSSL Man","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":8,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/36326221","title":"","type":null},"content":[{"type":"text","text":"ECC 椭圆曲线加密算法 - 介绍","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":9,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/44743146","title":"","type":null},"content":[{"type":"text","text":"ECC 椭圆曲线加密算法 - 有限域和离散对数","attrs":{}}]}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":10,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://zhuanlan.zhihu.com/p/66794410","title":"","type":null},"content":[{"type":"text","text":"ECC 椭圆曲线加密算法 - ECDH、ECDHE 和 ECDSA","attrs":{}}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。公众号后台回复【技术】可加入阿里云视频云技术交流群,和作者一起探讨音视频技术,获取更多行业最新信息。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章