STRP它是 思科的开源安全 RTP 库。RTP 是实时传输协议,一种用于传输实时数据(如电话、音频和视频)的 IETF 标准,由RFC 3550定义。SRTP用于为 RTP 数据提供机密性以及对 RTP 标头和有效负载进行身份验证。SRTP 是 IETF 标准,在RFC 3711中定义,该库支持 SRTP 的所有强制功能。
安装openssl加密库
git clone https://github.com/openssl/openssl/archive/refs/tags/openssl-3.0.1.tar.gz
cd openssl-3.0.1
./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl
make -j4 && make install
安装libsrtp库
git clone git clone https://github.com/cisco/libsrtp.git
cd libsrtp
./configure --prefix=/opt/srtp \
--with-openssl-dir=/opt/openssl \
--enable-openssl \
crypto_CFLAGS=/opt/openssl/include \
crypto_LIBS=/opt/openssl/lib64
V 2bits 版本号,版本2
P 1bit 填充位,当负载的长度不够32bits的整数倍时,需要填充位
X 1bit 扩展位,若为1,则固定的包头后增加一个32bits的扩展(rtp extension)
CC 4bits CSRC的数目
M 1bit 允许在比特流中标记重要的事件
PT 7bits 负载类型
seq16bits 每发送一个RTP数据包,序列号加1,根据此来判断序列号的顺序
时间戳 32bits
SSRC标识符 32bits synchronizating source identifier 识别同步源
CSRC标识符 n个32bits contributing source identifiers 识别负载重的有效贡献源
可选存在的RTP extension
加密的数据(末尾可能包含RTP padding和RTP pad count)
包尾是SRTP MKI(可选),master key identifier,是用来生成session加密密钥的随机位串标识符。
认证标签(Authentication tag)
SRTP加密之前双方需要进行加密算法和秘钥的协商,可以采用sip的协商方式进行协商。主要是在sip中增加:a=crypto字段用于存放加密类型和秘钥。那么问题来了秘钥这里是否需要进行加密,答案很显然需要进行秘钥的加密,不然就透明了你的秘钥第三方也可以获取秘钥进行解密操作。
srtp协商已经获取了双方的秘钥这时候可以利用秘钥进行加密操作,对方也可以利用秘钥对加密数据进行还原。
srtp_t session;
srtp_policy_t policy;
// Set key to predetermined value
uint8_t key[30] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D};
// initialize libSRTP
srtp_init();
// default policy values
memset(&policy, 0x0, sizeof(srtp_policy_t));
// set policy to describe a policy for an SRTP stream
srtp_crypto_policy_set_rtp_default(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
policy.ssrc = ssrc;
policy.key = key;
policy.next = NULL;
// allocate and initialize the SRTP session
srtp_create(&session, &policy);
// main loop: get rtp packets, send srtp packets
while (1) {
char rtp_buffer[2048];
unsigned len;
len = get_rtp_packet(rtp_buffer);
srtp_protect(session, rtp_buffer, &len);
send_srtp_packet(rtp_buffer, len);
}
srtp_t session;
srtp_policy_t policy;
// Set key to predetermined value
uint8_t key[30] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D};
// initialize libSRTP
srtp_init();
// default policy values
memset(&policy, 0x0, sizeof(srtp_policy_t));
// set policy to describe a policy for an SRTP stream
srtp_crypto_policy_set_rtp_default(&policy.rtp);
srtp_crypto_policy_set_rtcp_default(&policy.rtcp);
policy.ssrc = ssrc;
policy.key = key;
policy.next = NULL;
// allocate and initialize the SRTP session
srtp_create(&session, &policy);
// main loop: get rtp packets, send srtp packets
while (1) {
char rtp_buffer[2048];
unsigned len;
recv_srtp_packet(rtp_buffer, &len);
srtp_unprotect(session, rtp_buffer, &len);
//deal data
deal_data(rtp_buffer, len);
}