WebRTC 傳輸安全機制第二話:深入顯出 SRTP 協議

{"type":"doc","content":[{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過 ","attrs":{}},{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/tHW6sWRZUzkOtl2BsRbV1w","title":"","type":null},"content":[{"type":"text","text":"DTLS 協商","attrs":{}}]},{"type":"text","text":"後,RTC 通信的雙方完成 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"MasterKey","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"MasterSalt","attrs":{}}],"attrs":{}},{"type":"text","text":" 的協商。接下來,我們繼續分析在 WebRTC 中,如何使用交換的密鑰,來對 RTP 和 RTCP 進行加密,實現數據的安全傳輸。同時,本文會對 libsrtp 使用中,遇到的問題的進行解答,例如,什麼是 ROC,ROC 爲什麼是 32-bits?爲什麼會返回 error_code=9, error_code=10?交換的密鑰有生命週期嗎,如果有是多長時間呢?閱讀本篇之前建議閱讀","attrs":{}},{"type":"link","attrs":{"href":"https://mp.weixin.qq.com/s/tHW6sWRZUzkOtl2BsRbV1w","title":"","type":null},"content":[{"type":"text","text":" DTLS 協商篇","attrs":{}}]},{"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},"content":[{"type":"text","text":"作者|進學","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"審校|泰一","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":"codeinline","content":[{"type":"text","text":"RTP/RTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 協議並沒有對它的負載數據進行任何保護。因此,如果攻擊者通過抓包工具,如 Wireshark,將音視頻數據抓取到後,通過該工具就可以直接將音視頻流播放出來,這是非常恐怖的事情。","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 中,爲了防止這類事情發生,沒有直接使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP/RTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 協議,而是使用了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP/SRTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 協議 ,即安全的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP/RTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 協議。WebRTC 使用了非常有名的 libsrtp 庫將原來的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP/RTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 協議數據轉換成 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP/SRTCP","attrs":{}}],"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":"link","attrs":{"href":"https://datatracker.ietf.org/doc/html/rfc3711","title":"","type":null},"content":[{"type":"text","text":"SRTP","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":"對 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP/RTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 的負載 (payload) 進行加密,保證數據安全;","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"保證 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP/RTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 包的完整性,同時防重放攻擊。","attrs":{}}]}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"SRTP/SRTCP 結構","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"SRTP 結構","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b0/b0d65849547a19e1ac9daf0ca5ca1cb3.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":"從 SRTP 結構圖中可以看到:","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":"加密部分 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Encrypted Portion","attrs":{}}],"attrs":{}},{"type":"text","text":",由 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"payload","attrs":{}}],"attrs":{}},{"type":"text","text":", ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP padding","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP pad count","attrs":{}}],"attrs":{}},{"type":"text","text":" 部分組成。也就是我們通常所說的僅對 RTP 負載數據加密。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"需要校驗部分 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Authenticated Portion","attrs":{}}],"attrs":{}},{"type":"text","text":",由 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP Header","attrs":{}}],"attrs":{}},{"type":"text","text":", ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP Header extension","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Encrypted Portion","attrs":{}}],"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":"通常情況下只需要對 RTP 負載數據進行加密,如果需要對 RTP header extension 進行加密,","attrs":{}},{"type":"link","attrs":{"href":"https://datatracker.ietf.org/doc/html/rfc6904","title":"","type":null},"content":[{"type":"text","text":"RFC6904","attrs":{}}]},{"type":"text","text":" 給出了詳細方案,在 libsrtp 中也完成了實現。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"SRTCP 結構","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/91/916e6979f2c041fcc2c1f1990e5f3cec.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":"codeinline","content":[{"type":"text","text":"SRTCP","attrs":{}}],"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":"加密部分 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Encrypted Portion","attrs":{}}],"attrs":{}},{"type":"text","text":",爲 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTCP Header","attrs":{}}],"attrs":{}},{"type":"text","text":" 之後的部分,對 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Compound RTCP","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":"E-flag 顯式給出了 RTCP 包是否加密。(PS:一個 RTP 包怎麼判斷是加密的?)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"SRTCP index","attrs":{}}],"attrs":{}},{"type":"text","text":" 顯示給出了 RTCP 包的序列號,用來防重放攻擊。(PS:一個 RTP 包的 16-bits 的序列號可以防重放攻擊嗎?)","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":4,"align":null,"origin":null},"content":[{"type":"text","text":"待校驗部分 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Authenticated Portion","attrs":{}}],"attrs":{}},{"type":"text","text":",由 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTCP Header","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Encrypted Portion","attrs":{}}],"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":"在初步認識了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 的結構後,接下來介紹 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Encrypted Portion","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Authenticated Portion","attrs":{}}],"attrs":{}},{"type":"text","text":" 如何得到了。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Key 管理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP/SRTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 協議中,使用二元組 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" ","attrs":{}}],"attrs":{}},{"type":"text","text":"的方式來標識一個通信參與者的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP/SRTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 會話,稱爲 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP/SRTCP Session","attrs":{}}],"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":"在 SRTP 協議中使用三元組","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"","attrs":{}}],"attrs":{}},{"type":"text","text":"來標識一個 stream,一個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP/SRTCP Session","attrs":{}}],"attrs":{}},{"type":"text","text":" 由多個 stream 組成。對每個 stream 的加解密相關參數的描述,稱爲 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Cryptographic Context","attrs":{}}],"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":"每個 stream 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Cryptographic Context","attrs":{}}],"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":"SSRC: Stream 使用的 SSRC。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Cipher Parameter:加解密使用的 key, salt,算法描述 (類型,參數等)。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Authentication Parameter: 完整性使用的 Key, salt,算法描述 (類型,參數等)。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Anti-Replay Data: 防止重放攻擊緩存的數據信息,例如,ROC,最大序號等。","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":"codeinline","content":[{"type":"text","text":"SRTP/SRTCP Session","attrs":{}}],"attrs":{}},{"type":"text","text":" 中,每個 Stream 都會使用到屬於自己的,加解密 Key,Authentication Key。這些 Key 都是在同一個 Session 中使用到的,稱爲 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Session Key","attrs":{}}],"attrs":{}},{"type":"text","text":"。這些 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Session Key","attrs":{}}],"attrs":{}},{"type":"text","text":" 是通過對 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Master Key","attrs":{}}],"attrs":{}},{"type":"text","text":" 使用 KDF (Key Derivation Function) 導出的。","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":"KDF","attrs":{}}],"attrs":{}},{"type":"text","text":" 是用於導出 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Session Key","attrs":{}}],"attrs":{}},{"type":"text","text":" 函數,KDF 默認使用是加解密函數。例如,在完成 DTLS 後,協商得到的 SRTP 加密算法的 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":"KDF","attrs":{}}],"attrs":{}},{"type":"text","text":" 爲 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"AES128_CM","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Session Key","attrs":{}}],"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/f9/f998a5e93472ea59bb2ac1492269819f.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":"codeinline","content":[{"type":"text","text":"Session Key","attrs":{}}],"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":"codeinline","content":[{"type":"text","text":"key_label","attrs":{}}],"attrs":{}},{"type":"text","text":": 根據導出的 Key 的類型不同,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"key_label","attrs":{}}],"attrs":{}},{"type":"text","text":" 取值如下:","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":"none"},"content":[{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/20/20bf4c9ae525221674319ee6e82c2024.png","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":"text","text":"master_key: DTLS 完成後,協商得到的 Key。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"master_salt: DTLS 完成後,協商得到的 Salt。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"packet_index: RTP/RTCP 的包序號。SRTP 使用 48-bits 的隱式包需要,SRTCP 使用 31-bits 包序號。參考序號管理。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"key_derivation_rate: key 導出速率,記爲 kdr。默認取值爲 0,執行 1 次 Key 導出。取值範圍 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"{{1,2,4,...,2^24}","attrs":{}}],"attrs":{}},{"type":"text","text":"。在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"key_derivation_rate>0","attrs":{}}],"attrs":{}},{"type":"text","text":" 的情況下,在加密之前,執行一次 key 導出,後續在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"packet_index/key_derivation_rate > 0","attrs":{}}],"attrs":{}},{"type":"text","text":" 時,執行 key 導出。","attrs":{}}]}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"r = packet_index / kdr\nkey_id = label || r\nx = key_id XOR master_salt\nkey = KDF(master_key, x)\n","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":"'/':表示整除,B=0 時,C = A/B=0。||:表示連接的含義。A,B,C 使用網絡字節序表示,C = A||B, 則 C 的高字節爲 A,低字節位爲 B。XOR:是異或運算,計算時按照低字節位對齊。","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":"codeinline","content":[{"type":"text","text":"AES128_CM","attrs":{}}],"attrs":{}},{"type":"text","text":",舉例說明 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Session Key","attrs":{}}],"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":"master_key: E1F97A0D3E018BE0D64FA32C06DE4139 // 128-bits\nmaster_salt: 0EC675AD498AFEEBB6960B3AABE6 // 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":"導出加密 Key (cipher key):","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"packet_index/kdr: 000000000000\nlabel: 00\nmaster_salt: 0EC675AD498AFEEBB6960B3AABE6\n-----------------------------------------------\nxor: 0EC675AD498AFEEBB6960B3AABE6 (x, KDF input)\nx*2^16: 0EC675AD498AFEEBB6960B3AABE60000 (AES-CM input)\ncipher key: C61E7A93744F39EE10734AFE3FF7A087 (AES-CM output)\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":"導出 SALT Key (cipher salt):","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"packet_index/kdr: 000000000000\nlabel: 02\nmaster_salt: 0EC675AD498AFEEBB6960B3AABE6\n----------------------------------------------\nxor: 0EC675AD498AFEE9B6960B3AABE6 (x, KDF input)\nx*2^16: 0EC675AD498AFEE9B6960B3AABE60000 (AES-CM input)\n 30CBBC08863D8C85D49DB34A9AE17AC6 (AES-CM ouptut)\ncipher salt: 30CBBC08863D8C85D49DB34A9AE1\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":"導出校驗 Key (auth key),需要 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"auth key","attrs":{}}],"attrs":{}},{"type":"text","text":" 長度爲 94 字節:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"packet_index/kdr: 000000000000\nlabel: 01\nmaster salt: 0EC675AD498AFEEBB6960B3AABE6\n-----------------------------------------------\nxor: 0EC675AD498AFEEAB6960B3AABE6 (x, KDF input)\nx*2^16: 0EC675AD498AFEEAB6960B3AABE60000 (AES-CM input)\n\nauth key AES input blocks\nCEBE321F6FF7716B6FD4AB49AF256A15 0EC675AD498AFEEAB6960B3AABE60000\n6D38BAA48F0A0ACF3C34E2359E6CDBCE 0EC675AD498AFEEAB6960B3AABE60001\nE049646C43D9327AD175578EF7227098 0EC675AD498AFEEAB6960B3AABE60002\n6371C10C9A369AC2F94A8C5FBCDDDC25 0EC675AD498AFEEAB6960B3AABE60003\n6D6E919A48B610EF17C2041E47403576 0EC675AD498AFEEAB6960B3AABE60004\n6B68642C59BBFC2F34DB60DBDFB2 0EC675AD498AFEEAB6960B3AABE60005\n","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":"AES-CM 的介紹,參考","attrs":{}},{"type":"link","attrs":{"href":"https://www.rfc-editor.org/rfc/rfc3711.html#appendix-B.3","title":"","type":null},"content":[{"type":"text","text":" AES-CM","attrs":{}}]},{"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},"content":[{"type":"text","text":"至此,我們得到了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP/SRTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 加密和認證需要的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Session Key","attrs":{}}],"attrs":{}},{"type":"text","text":":cipher key,auth key,salt key。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"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":"在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"RTP","attrs":{}}],"attrs":{}},{"type":"text","text":" 包結構定義中使用 16-bit 來描述序列號。考慮到防重放攻擊,消息完整性校驗,加密數據,導出 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SessionKey","attrs":{}}],"attrs":{}},{"type":"text","text":" 的需要,在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP","attrs":{}}],"attrs":{}},{"type":"text","text":" 協議中,SRTP 包的序列號,使用隱式方式來記錄包序列號 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"packet_index","attrs":{}}],"attrs":{}},{"type":"text","text":",使用 i 標識 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"packet_index","attrs":{}}],"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":"對於發送端來說,i 的計算方式如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"i = 2^16 * ROC + SEQ\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":"其中,SEQ 是 RTP 包中描述的 16-bit 包序號。ROC (rollover couter) 是 RTP 包序號 (SEQ) 翻轉計數,也就是每當 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SEQ/2^16=0","attrs":{}}],"attrs":{}},{"type":"text","text":", ROC 計數加 1。ROC 初始值爲 0。","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":"ROC","attrs":{}}],"attrs":{}},{"type":"text","text":",還需要維護一個當前收到的最大包序號 s_l,當一個新的包到來時候,接收端需要估計出當前包所對應的實際 SRTP 包的序號。ROC 的初始值爲 0,s_l 的初始值爲收到第一個 SRTP 包的 SEQ。後續通過如下公式,估計接收到的 SRTP 序號 i:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"i = 2^16 * v + SEQ\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":"v ","attrs":{}}],"attrs":{}},{"type":"text","text":"可能的取值","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":" { ROC-1, ROC, ROC+1 }","attrs":{}}],"attrs":{}},{"type":"text","text":",ROC 是接收端本地維護的 ROC,SEQ 是收到 SRTP 的序號。v 分別取 ROC-1,ROC,ROC+1 計算出 i,與 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"2^16*ROC + s_l ","attrs":{}}],"attrs":{}},{"type":"text","text":" 進行比較,那個更接近,v 就取對應的值。完成 SRTP 解密和完整性校驗後,更新 ROC 和 s_l,分如下 3 種情況:","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":"v = ROC - 1, ROC 和 s_l 不更新。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"v = ROC,如果 SEQ > s_1,則更新 s_l = SEQ。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"v = ROC + 1, ROC = v = ROC + 1,s_l = SEQ。","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":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"if (s_l < 32768)\n if (SEQ - s_l > 32768)\n set v to (ROC-1) mod 2^32\n else\n set v to ROC\n endif\nelse\n if (s_l - 32768 > SEQ)\n set v to (ROC+1) mod 2^32\n else\n set v to ROC\n endif\nendif\nreturn SEQ + v*65536\n","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"SRTCP 序列號管理","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"RTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 中沒有描述序號的字段,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTCP","attrs":{}}],"attrs":{}},{"type":"text","text":" 的序號在 SRTCP 包,使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"31-bits","attrs":{}}],"attrs":{}},{"type":"text","text":" 中顯示描述,詳見 SRTCP 格式,也就是說在 SRTCP 的最大序列號爲 2^31。","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":"可以看到 SRTP 的序列號最大值爲 2^48, SRTCP 的序列號最大值爲 2^16。在大多數應用中(假設每 128000 個 RTP 數據包至少有一個 RTCP 數據包),SRTCP 序號將首先達到上限。以 200 SRTCP 數據包 / 秒的速度, SRTCP 的 2^31 序列號空間足以確保大約 4 個月的通信。","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":"攻擊者將截獲的 SRTP/SRTCP 包保存下來,然後重新發送到網絡中,實現了包的重放。SRTP 接收者通過維護一個重放列表 (ReplayList) 來防止這種攻擊。理論上 Replay List 應該保存所有接收到並完成校驗的包的序列號 index。在實際情況下 ReplayList 使用滑動窗口(sliding window)來實現防重放攻擊。使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP-WINDOW-SIZE","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 包的 SEQ,ROC,s_l 估算出 SRTP 包的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"packet_index","attrs":{}}],"attrs":{}},{"type":"text","text":" 的方法。同時,將接收者已經接收到 SRTP 包的最大序列號,記爲 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"local_packet_index","attrs":{}}],"attrs":{}},{"type":"text","text":"。計算差值 delta:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"delta = packet_index - local_packet_index\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":"分如下 3 種情況說明:","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":"delta > 0:表示收到了新的包。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"delta = -(SRTP-WINDOW-SIZE - 1)","attrs":{}}],"attrs":{}},{"type":"text","text":": 表示收到了重放窗口之內的包。如果在 ReplayList 找到對應的包,則是一個 index 重複的重放包。libSRTP 收到這樣的包時,會返回 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"srtp_err_status_replay_fail=9","attrs":{}}],"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":"下圖更加直觀說明防重放攻擊的三個區域:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/e3/e31a9ff769993866cd4340950949bfe0.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":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"SRTP-WINDOW-SIZE 的取值,最小是 64。應用可以根據需要設置成較大的值,libsrtp 會向上取整爲 32 的整數倍。例如,在 WebRTC 中 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTP-WINDOW-SIZE = 1024","attrs":{}}],"attrs":{}},{"type":"text","text":"。使用者可以根據需要進行調整,但要達到防重放攻擊的目的。","attrs":{}}]}],"attrs":{}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"SRTCP 防重放攻擊","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 SRTCP 中,packet index 顯式給出。在 libsrtp 中,SRTCP 的防重放攻擊的窗口大小爲 128。使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"window_start","attrs":{}}],"attrs":{}},{"type":"text","text":" 記錄防重放攻擊的起始序列號。SRTCP 防重放攻擊的檢查步驟如下:","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":"index > window_start + 128: 收到新的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SRTCP","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":"index < window_start: 收到包的序列號在重放窗口的左側,可以認爲我們收到了比較老的包。libsrtp 收到這樣的包之後,會返回到 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"srtp_err_status_replay_old=10","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]}]},{"type":"listitem","attrs":{"listStyle":null},"content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"replay_list_index = index - windwo_start:在 ReplayList 中 replay_list_index 對應的標識位爲 1,表示已經收到包,libsrtp 返回 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"srtp_err_status_replay_fail=9","attrs":{}}],"attrs":{}},{"type":"text","text":"。對應的標識位爲 0,表示收到亂序包。","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":"在 SRTP 中,使用了 CTR(Counter mode)模式的 AES 加密算法,CTR 模式通過遞增一個加密計數器以產生連續的密鑰流,計數器可以是任意保證長時間不產生重複輸出的密鑰。根據計數方式的不同,分爲以下兩種類型:","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":"AES-ICM","attrs":{}}],"attrs":{}},{"type":"text","text":": ICM 模式(Integer Counter Mode,整數計數模式),使用整數計數運算。","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":"AES-GCM","attrs":{}}],"attrs":{}},{"type":"text","text":": GCM 模式(Galois Counter Mode,基於伽羅瓦域計數模式),計數運算定義在伽羅瓦域。","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":"codeinline","content":[{"type":"text","text":"AES-ICM","attrs":{}}],"attrs":{}},{"type":"text","text":" 完成加密算法,同時使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"HMAC-SHA1","attrs":{}}],"attrs":{}},{"type":"text","text":" 完成 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"MAC","attrs":{}}],"attrs":{}},{"type":"text","text":" 計算,對數據進行完整性校驗,加密和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"MAC","attrs":{}}],"attrs":{}},{"type":"text","text":" 計算需要分兩步完成。","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"AES-GCM","attrs":{}}],"attrs":{}},{"type":"text","text":" 基於 AEAD(Authenticated-Encryption with Associated-Data,關聯數據的認證加密)的思想,在對數據進行加密的同時計算 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"MAC","attrs":{}}],"attrs":{}},{"type":"text","text":" 值,實現了一個步驟,完成加密和校驗信息的計算。下面分別對這個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"AES-ICM","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"AES_GSM","attrs":{}}],"attrs":{}},{"type":"text","text":" 的用法進行介紹。","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"AEC—ICM","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/77/773d6277a7882449a615f5fedf216185.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":"codeinline","content":[{"type":"text","text":"AES-ICM","attrs":{}}],"attrs":{}},{"type":"text","text":" 的加密和解密過程,圖中的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"K","attrs":{}}],"attrs":{}},{"type":"text","text":" 是通過 KDF 導出的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"SessionKey","attrs":{}}],"attrs":{}},{"type":"text","text":"。加密和加密都是通過對 Counter 進行加密,與明文 P 異或運算得到加密數據 C,反之,與密文 C 異或運算得到明文數據 P。考慮到安全性,Counter 生成依賴於 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"Session Salt","attrs":{}}],"attrs":{}},{"type":"text","text":", 包的索引(packet index)和包的 SSRC。Counter 是 128-bits 的計數,生成方式如下定義:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"text"},"content":[{"type":"text","text":"one byte\n\n0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\n|00|00|00|00| SSRC | packet index | b_c |---+\n+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |\n |\n+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ v\n| salt (k_s) |00|00|->(+)\n+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |\n |\n v\n +-------------+\n encryption key (k_e) -> | AES encrypt |\n +-------------+\n |\n+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |\n| keystream block | B。當 K 長度大於 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":" 時候,會先在 K 上面執行 hash 算法,將得到的 L 長度結果作爲新的共享密鑰。如果 K 的長度
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章