前端面试题:如何用 WebRTC Encoded Transform 实现端到端加密?
题干
请为多人 WebRTC 会议设计浏览器端端到端加密方案:媒体服务器只转发 RTP,无法读取音视频内容;发送端和接收端在 Worker 中处理编码帧。说明 RTCRtpScriptTransform、RTCRtpScriptTransformer、密钥分发、关键帧、性能、失败恢复与兼容性边界。回答必须区分编码帧变换与传输层 TLS。
面试官在考察什么
核心是浏览器媒体管线的边界设计。面试官会看你是否把变换放在编码后、解码前,是否保证每帧按序流经 readable 到 writable,是否通过 Worker 隔离 CPU 工作,是否处理密钥轮换、加入会议的关键帧、丢帧和不支持该 API 的浏览器。只说“加密 RTP”而不描述帧生命周期,信息不足。
先澄清这几个问题
- 需要保护哪些参与者和媒体服务器?是否允许服务器转发但不能解密?
- 只支持视频还是音频也要加密?是否需要屏幕共享和录制?
- 密钥由端到端信令分发,还是已有群组密钥服务?如何撤销离会成员?
- 目标浏览器和最低版本是什么?不支持 Encoded Transform 时是拒绝加入、降级还是关闭 E2EE?
30 秒框架
先说明 TLS 只保护传输链路,媒体服务器仍可能看到解密后的媒体;E2EE 要在发送端编码后加密、接收端解密后交给解码器。方案分五层:能力检测、Worker 帧管线、密钥与 nonce、关键帧和重试、降级与观测。API 在现代浏览器中属 Baseline 2025,但仍要按浏览器矩阵验证。
逐步拆解方案
1. 能力检测与挂接时机
创建 RTCRtpScriptTransform 时传入 Worker、方向标识和可转移的 MessagePort。发送端在 RTCRtpSender.transform 上挂接,接收端在 RTCRtpReceiver.transform 上挂接;应尽早挂接,避免第一帧绕过变换。能力检测失败时记录原因,不把未加密媒体静默当成成功。
2. Worker 中的帧流
Worker 监听 rtctransform 事件,从 event.transformer.readable 读取编码帧,经过 TransformStream 后写入 event.transformer.writable。变换必须保持顺序、恰好一次入队,并在异常时关闭流和上报状态。主线程只传递配置和密钥句柄,避免在 UI 线程执行逐帧密码运算。
3. 加密格式与密钥生命周期
为每个会议、发送者和密钥 epoch 建立上下文;nonce 由帧序号、SSRC 或显式计数器构造,绝不能复用。密文携带版本、epoch 和认证标签,接收端先验证再解密。密钥通过已认证的端到端信令分发,轮换时允许短暂双 epoch,成员离会立即撤销新帧权限。
4. 关键帧与新成员加入
新成员可能先收到 delta frame,无法仅靠它重建画面。接收端变换在获得新密钥或发现无法解码时调用 sendKeyFrameRequest();发送端变换可调用 generateKeyFrame()。两者都返回 Promise,调用前要确认方向和视频状态,并对频繁请求做限流。
5. 性能与背压
控制加密算法的内存复制和 GC,优先复用帧缓冲;Worker 维持固定并发,避免无界队列。统计每帧变换耗时、排队深度、丢帧率和关键帧请求率。若加密延迟超过预算,降低视频质量或暂时暂停轨道,不能让主线程卡顿。
6. 错误、重连与恢复
密钥过期、认证标签失败、Worker 崩溃和浏览器拒绝调用都要进入可观测状态机。短暂失败可重启 Worker 并从当前 epoch 恢复;无法恢复时停止发送该轨道并提示用户。重新协商 PeerConnection 后重新挂接 transform,不能假设旧 Worker 仍关联新 sender。
7. 兼容性与安全边界
MDN 将 Encoded Transform 标为 Baseline 2025,但旧浏览器和部分设备仍可能缺失。产品策略要明确拒绝加入、端到端关闭或只允许受信媒体服务器转码。W3C 规范是 Working Draft,不能把接口稳定性、密码套件或浏览器实现差异隐藏在“已支持”标签后。
一份合格回答示例
“我会在 sender 编码后和 receiver 解码前分别挂接 RTCRtpScriptTransform,Worker 从 transformer 的 readable 读取编码帧,经带认证的加密 TransformStream 后写入 writable。密钥由端到端信令按会议、参与者和 epoch 管理,nonce 使用不可重复的帧计数器,接收端验证标签后才解密。新成员或密钥切换导致无法解码时,接收端限流调用 sendKeyFrameRequest,发送端必要时 generateKeyFrame。监控变换耗时、排队、丢帧和认证失败;Worker 或密钥恢复失败就停止该轨道。上线前按浏览器能力检测决定拒绝、降级或关闭 E2EE,并注明 API 的 Baseline 2025 与 W3C Working Draft 状态。”
常见失分点
- 把 TLS 当作媒体端到端加密,忽略服务器可见明文的边界。
- 在主线程逐帧加密,或把原始帧而非编码帧送进自定义管线。
- 不验证认证标签、复用 nonce,或没有 epoch 与离会撤销策略。
- 忽略关键帧请求、Worker 崩溃、重连和浏览器能力差异。
- 只报“支持 WebRTC”,没有验证 Encoded Transform 的具体接口。
追问方向
为什么要在编码后处理?
编码帧体积更小且保留 RTP 管线,变换可在浏览器解码前后插入;原始帧会增加复制和计算成本。
sendKeyFrameRequest() 一定会发送吗?
不一定。用户代理可能判断请求没有必要,Promise 仍可成功完成,所以产品应继续处理等待和超时。
密钥如何传给 Worker?
通过 RTCRtpScriptTransform 的可序列化 options 或转移 MessageChannel 传递短期句柄,避免把长期密钥暴露给无关脚本。
不支持 API 时能否静默降级?
不能。必须向用户和会议策略明确当前媒体是否 E2EE;静默降级会破坏安全承诺。
如何验证没有服务器明文?
在测试环境抓取转发节点可见数据,验证只有密文帧;同时审计信令、Worker、密钥服务和录制路径的权限与日志。
参考资料
MDN《Using WebRTC Encoded Transforms》、MDN《RTCRtpScriptTransformer》与 W3C《WebRTC Encoded Transform》规范草案。