跳到主要内容

3.3.1. Packet Index Determination, and ROC, s_l Update (数据包索引确定和 ROC, s_l 更新)

3.3.1. Packet Index Determination, and ROC, s_l Update (数据包索引确定和 ROC, s_l 更新)

SRTP 实现使用"隐式"数据包索引 (implicit packet index) 进行排序, 即并非所有索引都在 SRTP 数据包中明确携带。对于预定义的转换, 索引 i 用于重放保护 (Section 3.3.2)、加密 (Section 4.1)、消息认证 (Section 4.2) 和密钥派生 (Section 4.3)。

当会话开始时, 发送方必须将翻转计数器 ROC (rollover counter) 设置为零。每次 RTP 序列号 SEQ 模 2^16 回绕时, 发送方必须将 ROC 模 2^32 加一 (参见下面的安全方面)。发送方的数据包索引定义为

i = 2^16 * ROC + SEQ.

接收方实现使用 RTP 序列号来确定数据包的正确索引, 即数据包在所有 SRTP 数据包序列中的位置。翻转计数器正确使用的稳健方法要求其处理和使用被明确定义。特别是, 序列号接近 2^16 或零的乱序 RTP 数据包必须得到正确处理。

索引估计基于接收方本地维护的 ROC 和 s_l 值。在会话设置时, ROC 必须设置为零。加入正在进行的会话的接收方必须使用带外信令 (out-of-band signaling) (如密钥管理信令) 获得当前 ROC 值。此外, 接收方应当将 s_l 初始化为观察到的第一个 SRTP 数据包的 RTP 序列号 SEQ (除非初始值由带外信令如密钥管理提供)。

对于连续的 SRTP 数据包, 接收方应该将索引估计为

i = 2^16 * v + SEQ,

其中 v 从集合 { ROC-1, ROC, ROC+1 } (模 2^32) 中选择, 使得 i 在模 2^48 意义上最接近值 2^16 * ROC + s_l (参见 Appendix A 中的伪代码)。

在数据包已被处理和认证后 (当会话的 SRTP 数据包启用时), 接收方必须使用 v 有条件地更新其 s_l 和 ROC 变量, 如下所示。如果 v=(ROC-1) mod 2^32, 则不更新 s_l 或 ROC。如果 v=ROC, 则当且仅当 SEQ 大于当前 s_l 时将 s_l 设置为 SEQ; ROC 不变。如果 v=(ROC+1) mod 2^32, 则将 s_l 设置为 SEQ 并将 ROC 设置为 v。

在重新密钥 (re-keying) 发生后 (更改为新的主密钥), 翻转计数器始终保持其值序列, 即它不得重置为零。

由于翻转计数器为 32 位长, 序列号为 16 位长, 因此使用预定义的转换, 可以用相同密钥保护的属于给定 SRTP 流的最大数据包数为 2^48。在用给定的 (主密钥或会话) 密钥发送了该数量的 SRTP 数据包后, 发送方不得再用该密钥发送任何数据包。(SRTCP 存在类似的限制, 在实践中可能更具限制性, 参见 Section 9.2。) 此限制通过提供加密密钥更改之前可以通过的流量上限来强制实施安全优势。在此流量之前必须触发重新密钥 (参见 Section 8.1), 并且可以更早触发, 例如为了增强安全性和对媒体的访问控制。通过非零 key_derivation_rate (参见 Section 4.3) 进行的循环密钥派生也提供了更强的安全性, 但不会改变上述绝对最大值。

在接收方, 更新 s_l 和 ROC 有一个注意事项: 如果不存在消息认证, 则 s_l 的初始化和 ROC 更新都无法完全稳健。对于预定义的转换, 只要数据包的重排序和丢失不太严重且位错误不以不幸的方式发生, 接收方的"隐式索引"方法就有效。特别是, 需要丢失 2^15 个数据包, 或者数据包需要乱序 2^15 个数据包才会失去同步。如此剧烈的丢失或重排序可能会破坏 RTP 应用程序本身。

索引估计和 ROC 更新的算法是实现问题, 应该考虑环境 (例如数据包丢失率) 以及可能失去同步的情况, 例如当初始序列号 (由 RTP 随机选择) 事先未知 (未在密钥管理协议中发送) 但可能接近模 2^16 回绕时。

比上述方案更复杂且更稳健的方案是 RTP 自己的"翻转计数器"的处理, 参见 [RFC3550] 的 Appendix A.1。