SRTP 加密媒体 · SrtpSession 与 libsrtp

密钥就位,SRTP 开始加密每一个媒体包。这一章读 pc/srtp_session.h 与 srtp_transport.h:SrtpSession 如何封装 libsrtp、ProtectRtp/UnprotectRtp 就地加解密、SrtpTransport 怎么管 RTP 与 RTCP 两个会话,以及 rtcp-mux 如何省掉一个。

作者 David更新于 第 30 篇(共 112 篇)

SRTP 加密媒体 · SrtpSession 与 libsrtp

密钥导出完成,终于到了安全模型的最后一环:SRTP 真正加密每一个媒体包。这活儿由 SrtpSession 干,它背后是业界标准库 libsrtp。这一章读它,收束「加密」这条线。

SrtpSession:封装 libsrtp

SrtpSession(pc/srtp_session.h)不自己实现密码学,而是封装 Cisco 的 libsrtp(g3doc/srtp.md):

The SrtpSession is providing encryption and decryption of SRTP packets using libsrtp.

加解密的四个动词,就是 SrtpSession 的核心 API——而且都是「就地(in-place)」操作:

// pc/srtp_session.h(节选)
bool ProtectRtp(...);      // 加密一个 RTP 包(发送侧)
bool ProtectRtcp(...);     // 加密一个 RTCP 包
bool UnprotectRtp(...);    // 解密一个 RTP 包(接收侧)
bool UnprotectRtcp(...);   // 解密一个 RTCP 包

就地意味着:加解密直接在包的缓冲区上进行,不额外拷贝一份——对每秒成百上千个媒体包的实时系统,这点性能优化很实在。发送侧:RTP 打包好一个包 → ProtectRtp 就地加密 → 发出。接收侧:收到密文包 → UnprotectRtp 就地解密 → 交给 RTP 处理。密钥则由上游的 DtlsSrtpTransport 通过 SetSend / SetReceive 提前配好。

SrtpSession 还负责 libsrtp 的初始化与去初始化——它用引用计数追踪「当前有多少个实例在用 libsrtp」,最后一个走了才清理,避免重复 init/deinit(g3doc/srtp.md)。

SRTP 保护了什么

SRTP 对一个 RTP 包做的,不只是「加密」:

  • 机密性(加密) —— 用 AES 加密 RTP 的负载(媒体数据),链路上偷看只见密文。注意 RTP 头部通常不加密(路由、多路复用要看头),但被认证保护。
  • 完整性 + 认证(HMAC) —— 给包附一个认证标签(如 HMAC-SHA1),接收方校验:包没被篡改、且确实来自持有密钥的对端。篡改一个比特,校验就失败,包被丢弃。
  • 抗重放 —— SRTP 记住收过的序号,重复的旧包(攻击者录下来重发)会被识别并拒绝。

所以 SRTP 是「加密 + 认证 + 抗重放」三合一——实时媒体安全需要的,它都给了。GCM 套件更是把加密和认证合成一步(AEAD),更高效。

SrtpTransport:管两个会话

SrtpSession 处理单向的一类包,但一条媒体流有 RTP 和 RTCP(第 4 部分细讲 RTCP 是反馈信道)。管理它们的是 SrtpTransport(pc/srtp_transport.h,也是 DtlsSrtpTransport 的基类),g3doc/srtp.md:

SrtpTransport is controlling the SrtpSession instances for RTP and RTCP.

正常要两个 SrtpSession(一个护 RTP、一个护 RTCP)。但——

用了 rtcp-mux,就只需要一个 SrtpSession。 rtcp-mux(RFC 5761)让 RTCP 和 RTP 复用同一个端口 / 传输(又是 WebRTC 「一条路承载一切」的体现)。g3doc/srtp.md 说明:「When rtcp-mux is used, the SrtpSession for RTCP is not needed.」——RTCP 既然和 RTP 走同一条加密流,自然共用同一个 SRTP 会话,省掉一个。现代 WebRTC 默认开 rtcp-mux,所以通常一条媒体一个 SrtpSession 足矣。

一张加密流水线图

把整个第 3 部分串起来,发送一个媒体包的安全流水线:

图表加载中…

小结与下一章

SRTP 加密每个媒体包,由 SrtpSession(pc/srtp_session.h)封装 libsrtp 实现:ProtectRtp / UnprotectRtp(及 RTCP 版)就地加解密,密钥由上游 DtlsSrtpTransport 配好。SRTP 提供加密 + 认证(HMAC)+ 抗重放三合一(GCM 套件用 AEAD 合并)。SrtpTransport 管 RTP 与 RTCP 两个会话,而 rtcp-mux 让二者复用、省掉一个。

加解密和握手都靠一个底层密码库——BoringSSL。下一章看 WebRTC 怎么接这个 SSL 库,以及 OpenSSLStreamAdapter 的角色。👉 BoringSSL 集成。

参考资料

  • [1] libwebrtc 源码.pc/srtp_session.h / .cc(ProtectRtp / UnprotectRtp、libsrtp 封装)、pc/srtp_transport.h、g3doc/srtp.md。
  • [2] libsrtp.https://github.com/cisco/libsrtp —— SRTP 参考实现。
  • [3] IETF RFC 3711「SRTP」、RFC 5761「RTP/RTCP 复用」。

本页目录