SRTP协议是什么
SRTP,即安全实时传输协议(Secure Real-time Transport Protocol),是在实时传输协议(Real-time Transport Protocol)基础上所定义的一个协议。
SRTP协议格式
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<+
|V=2|P|X| CC |M| PT | sequence number | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| timestamp | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| synchronization source (SSRC) identifier | |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
| contributing source (CSRC) identifiers | |
| .... | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| RTP extension (OPTIONAL) | |
+>+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| | payload ... | |
| | +-------------------------------+ |
| | | RTP padding | RTP pad count | |
+>+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<+
| ~ SRTP MKI (OPTIONAL) ~ |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| : authentication tag (RECOMMENDED) : |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| |
+- Encrypted Portion* Authenticated Portion ---+
字段介绍
前面12个字节和CSRC与RTP头中相应字段完全一样,唯一不同的是SRTP新添加了MKI和authentication tag两个字段, 两个字段位于加密body的尾部。
rtp头各字段的含义等到下篇介绍RTP时再介绍。
SRTP MKI
MKI :Master Key Identifier,主密钥标识。
srtp有两种类型的key,一个是master key,一个是session key。通过dtls协商的秘钥是和master key相关的,内部会经过一定的处理逻辑最终生成session key(生成规则见文章末尾),通过session key对数据进行加密。
不同的会话对应不同的session key,而MKI的值其实是session key 的mki_id, 用来区分不同的session key。
具体代码如下:
unsigned int srtp_inject_mki(uint8_t *mki_tag_location,
srtp_session_keys_t *session_keys,
unsigned int use_mki)
{
unsigned int mki_size = 0;
if (use_mki) {
mki_size = session_keys->mki_size;
if (mki_size != 0) {
// Write MKI into memory
//把session_keys的mki_id 填到mki字段
memcpy(mki_tag_location, session_keys->mki_id, mki_size);
}
}
return mki_size;
}
转到session_keys结构定义处,会看到mki_id的说明,它是用来确定session keys
/*
* srtp_session_keys_t will contain the encryption, hmac, salt keys
* for both SRTP and SRTCP. The session keys will also contain the
* MKI ID which is used to identify the session keys.
*/
typedef struct srtp_session_keys_t {
srtp_cipher_t *rtp_cipher;
srtp_cipher_t *rtp_xtn_hdr_cipher;
srtp_auth_t *rtp_auth;
srtp_cipher_t *rtcp_cipher;
srtp_auth_t *rtcp_auth;
uint8_t salt[SRTP_AEAD_SALT_LEN];
uint8_t c_salt[SRTP_AEAD_SALT_LEN];
uint8_t *mki_id;
unsigned int mki_size;
srtp_key_limit_ctx_t *limit;
} srtp_session_keys_t;
通过看srtp源码,发现并没有用mki,默认取session_keys列表中的第一个值作为session key。
加密时use_mki和mki_index都为0,同样解密时mki_index也为0。
srtp_err_status_t srtp_protect(srtp_ctx_t *ctx,
void *rtp_hdr,
int *pkt_octet_len)
{
//use_mki和mki_index两个参数都是0
return srtp_protect_mki(ctx, rtp_hdr, pkt_octet_len, 0, 0);
}
srtp_err_status_t srtp_protect_mki(srtp_ctx_t *ctx,
void *rtp_hdr,
int *pkt_octet_len,
unsigned int use_mki,
unsigned int mki_index)
authentication tag
SRTP包的认证tag,认证的的数据由RTP头和SRTP包的加密部分组成。就是对数据进行签名,然后收到消息后再进行一次,对比两次生成的结果是否相等,来确定数据是否正确。
SRTP对RTP加密时只加密RTP的playload部分,不加密RTP头。代码如下
/*
* find starting point for encryption and length of data to be
* encrypted - the encrypted portion starts after the rtp header
* extension, if present; otherwise, it starts after the last csrc,
* if any are present
*
* if we're not providing confidentiality, set enc_start to NULL
*/
if (stream->rtp_services & sec_serv_conf) {//跳过rtp header
enc_start = (uint32_t *)hdr + uint32s_in_rtp_header + hdr->cc;
if (hdr->x == 1) {
xtn_hdr = (srtp_hdr_xtnd_t *)enc_start;
enc_start += (ntohs(xtn_hdr->length) + 1);
}
/* note: the passed size is without the auth tag */
if (!((uint8_t *)enc_start <= (uint8_t *)hdr + *pkt_octet_len))
return srtp_err_status_parse_err;
enc_octet_len =
(int)(*pkt_octet_len - ((uint8_t *)enc_start - (uint8_t *)hdr));
if (enc_octet_len < 0)
return srtp_err_status_parse_err;
} else {
enc_start = NULL;
}
所以,如果项目中是以SSRC为key保存用户信息,当收到SRTP包无需解密也可以获得包中的SSRC,从而找到用户。
但是,对于rtp的扩展头是加密的,代码如下,详情见RFC6904
if (xtn_hdr && session_keys->rtp_xtn_hdr_cipher) {
/*
* extensions header encryption RFC 6904
*/
status = srtp_process_header_encryption(stream, xtn_hdr, session_keys);
if (status)
{
return status;
}
}
srtp加密上下文信息
描述srtp加密时用的一些基础知识,参数信息
- ROC (Rollover Counter) 序列号重置
rtp的序列号占16位,当超过最大值时,序列号会再从零开始,因为包又从零开始,那怎么区分不同的包呢?为了解决这个问题,引入了重置次数ROC,重置后RTP包序列号计算公式:
i = 2^16 * ROC + SEQ
每重置一次相当于经过了2^16个包,重置几次既有几个2^16次方,SEQ是当前RTP包头中的序列号。
- master saltmaster key的”盐值”,就是对master key加上一些随机值,然后进行散列。
基于master key和master salt推导出实际加密rtp时用的session key。
packet index ---+
|
v
+-----------+ master +--------+ session encr_key
| ext | key | |---------->
| key mgmt |-------->| key | session auth_key
| (optional | | deriv |---------->
| rekey) |-------->| | session salt_key
| | master | |---------->
+-----------+ salt +--------+
作者:音视频之路
版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。