DTLS-SRTP 密钥导出 · 从握手到 SRTP 密钥
DTLS 握手不直接加密媒体,而是导出一份「密钥材料」交给 SRTP。这一章读 pc/dtls_srtp_transport.h:DtlsSrtpTransport 如何在握手完成时用 ExportKeyingMaterial 抽取密钥、配置给 SrtpSession,以及为什么它「握手完成后才变 writable」。
DTLS-SRTP 密钥导出 · 从握手到 SRTP 密钥
DTLS 握手成功了,身份也验明了。但 DTLS 本身不加密媒体——它只负责谈密钥。这一章讲清「谈好的密钥」怎么变成 SRTP 真正能用的钥匙——这一步叫密钥导出,是 DTLS-SRTP 的枢纽。
承上启下:DtlsSrtpTransport
干这个枢纽活的,是 DtlsSrtpTransport(pc/dtls_srtp_transport.h)。g3doc/srtp.md 一句话点透它的身份:
DtlsSrtpTransportis a subclass of theSrtpTransportthat extracts the keying material when the DTLS handshake is done and configures it in its base class.
导出:ExportKeyingMaterial
「从 DTLS 会话里抽密钥」的机制,是 TLS 标准的 ExportKeyingMaterial(密钥导出函数)。它的思想很优雅:
DTLS 握手过程中,双方其实已经共同算出了一批共享密钥(主密钥及派生);ExportKeyingMaterial 让上层能从这批密钥里,「导出」额外的、用于其他用途的密钥——这里就是 SRTP 的密钥。 关键在于:导出是确定性的——双方用同一个「标签」(DTLS-SRTP 规定的字符串)和同样的握手密钥,导出完全相同的 SRTP 密钥材料,却无需再传输任何密钥。密钥从不上网,只在两端各自「算」出来,天然抗窃听。
导出的材料按 DTLS-SRTP 协商的套件切成:发送方向的密钥 + 盐、接收方向的密钥 + 盐。DtlsSrtpTransport 拿到后,分别配置给 SRTP 的发送和接收会话(SetSend / SetReceive)。至此,SRTP 万事俱备。
为什么握手完才 writable
g3doc/srtp.md 还提到 DtlsSrtpTransport 一个重要行为:
It will also become writable only once the DTLS handshake is done.
这个「握手完才可写」是安全的强约束:在密钥导出之前,SRTP 没有钥匙,任何媒体包都无法加密——所以 DtlsSrtpTransport 在握手完成、密钥就位之前,拒绝发送任何媒体。这从机制上杜绝了明文媒体外泄的可能:哪怕上层编码器已经出帧了,只要 DTLS 没握手完,这些帧就发不出去。「没有密钥,就没有媒体」——强制加密的底线,在这里被 writable 状态硬性保证。
小结与下一章
DTLS-SRTP 密钥导出是 DTLS 握手和 SRTP 加密之间的桥,由 DtlsSrtpTransport(SrtpTransport 的子类)完成:握手一结束,用 ExportKeyingMaterial 从 DTLS 共享密钥里确定性地导出 SRTP 密钥材料(双方各自算出、完全一致、无需再传输),按套件切成收发密钥配给 SRTP 会话。它握手完成才 writable——没密钥就不发媒体,硬性杜绝明文外泄。
密钥到手,终于可以加密媒体了。下一章看真正干加解密的 SrtpSession 和它背后的 libsrtp。👉 SRTP 加密媒体。
参考资料
- [1] libwebrtc 源码.
pc/dtls_srtp_transport.h/.cc(DtlsSrtpTransport、导出密钥、writable 时机)、g3doc/srtp.md。 - [2] libwebrtc 源码.
rtc_base/ssl_stream_adapter.h(ExportKeyingMaterial)。 - [3] IETF RFC 5764「DTLS-SRTP」§ Key Derivation;RFC 5705「TLS 密钥材料导出」。