詳解 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}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章