我正在尝试构建一个SRTP
到RTP
流转换器,但我在创建Master Key
时遇到WebRTC peerconnection
时出现问题。
根据我的理解,使用DES exchange,关键是通过SDP
交换进行交换,并显示在a=crypto
字段中。所以,这种情况看起来非常简单(如果我错了请纠正我),但最终无用,因为WebRTC
标准化现在要求不应该使用DES(现在只有Chrome
支持它并且可能将来要删除。)
对于DTLS,SDP
中有指纹字段,是未来交换中使用的certificate desired的哈希值吗?[编辑:做了一些阅读后,我我认为情况并非如此]我会想到指纹的一致性,在交换中解析DTLS数据包的能力,我应该能够抓住Master Key
来解码SRTP流,但是我我正在撞墙,因为我不知道在哪里看,甚至100%确定是否有可能。
因此,简而言之,它是否可行(没有进入较低的C ++ API并创建我自己的WebRTC
实现)来解码使用{{1}创建的SRTP
Feed在WebRTC PeerConnection
和Chrome
中(可能通过数据包嗅探从FireFox
交换机收集的信息)?[编辑:令人沮丧的是,它似乎可以访问密钥的私有部分(又名) ,主密钥)是不可能的......如果我错了请纠正]
答案 0 :(得分:6)
这是使用openssl和libsrtp native api
的一些代码#define SRTP_MASTER_KEY_KEY_LEN 16
#define SRTP_MASTER_KEY_SALT_LEN 14
static void dtls_srtp_init( struct transport_dtls *dtls )
{
/*
When SRTP mode is in effect, different keys are used for ordinary
DTLS record protection and SRTP packet protection. These keys are
generated using a TLS exporter [RFC5705] to generate
2 * (SRTPSecurityParams.master_key_len +
SRTPSecurityParams.master_salt_len) bytes of data
which are assigned as shown below. The per-association context value
is empty.
client_write_SRTP_master_key[SRTPSecurityParams.master_key_len];
server_write_SRTP_master_key[SRTPSecurityParams.master_key_len];
client_write_SRTP_master_salt[SRTPSecurityParams.master_salt_len];
server_write_SRTP_master_salt[SRTPSecurityParams.master_salt_len];
*/
int code;
err_status_t err;
srtp_policy_t policy;
char dtls_buffer[SRTP_MASTER_KEY_KEY_LEN * 2 + SRTP_MASTER_KEY_SALT_LEN * 2];
char client_write_key[SRTP_MASTER_KEY_KEY_LEN + SRTP_MASTER_KEY_SALT_LEN];
char server_write_key[SRTP_MASTER_KEY_KEY_LEN + SRTP_MASTER_KEY_SALT_LEN];
size_t offset = 0;
/*
The exporter label for this usage is "EXTRACTOR-dtls_srtp". (The
"EXTRACTOR" prefix is for historical compatibility.)
RFC 5764 4.2. Key Derivation
*/
const char * label = "EXTRACTOR-dtls_srtp";
SRTP_PROTECTION_PROFILE * srtp_profile= SSL_get_selected_srtp_profile( dtls->ssl );
/* SSL_export_keying_material exports a value derived from the master secret,
* as specified in RFC 5705. It writes |olen| bytes to |out| given a label and
* optional context. (Since a zero length context is allowed, the |use_context|
* flag controls whether a context is included.)
*
* It returns 1 on success and zero otherwise.
*/
code = SSL_export_keying_material(dtls->ssl,
dtls_buffer,
sizeof(dtls_buffer),
label,
strlen( label),
NULL,
0,
PJ_FALSE);
memcpy(&client_write_key[0], &dtls_buffer[offset], SRTP_MASTER_KEY_KEY_LEN);
offset += SRTP_MASTER_KEY_KEY_LEN;
memcpy(&server_write_key[0], &dtls_buffer[offset], SRTP_MASTER_KEY_KEY_LEN);
offset += SRTP_MASTER_KEY_KEY_LEN;
memcpy(&client_write_key[SRTP_MASTER_KEY_KEY_LEN], &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
offset += SRTP_MASTER_KEY_SALT_LEN;
memcpy(&server_write_key[SRTP_MASTER_KEY_KEY_LEN], &dtls_buffer[offset], SRTP_MASTER_KEY_SALT_LEN);
switch( srtp_profile->id )
{
case SRTP_AES128_CM_SHA1_80:
crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtp);
crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp);
break;
case SRTP_AES128_CM_SHA1_32:
crypto_policy_set_aes_cm_128_hmac_sha1_32(&policy.rtp); // rtp is 32,
crypto_policy_set_aes_cm_128_hmac_sha1_80(&policy.rtcp); // rtcp still 80
break;
default:
assert(0);
}
policy.ssrc.value = 0;
policy.next = NULL;
/* Init transmit direction */
policy.ssrc.type = ssrc_any_outbound;
policy.key = client_write_key;
err = srtp_create(&dtls->srtp_ctx_rx, &policy);
if (err != err_status_ok) {
printf("not working\n");
}
/* Init receive direction */
policy.ssrc.type = ssrc_any_inbound;
policy.key = server_write_key;
err = srtp_create(&dtls->srtp_ctx_tx, &policy);
if (err != err_status_ok) {
printf("not working\n");
}
}
答案 1 :(得分:3)
我找到了'SSL_export_keying_material' 哪个可以从SSL机制获取密钥(在DTLS握手之后)并将其用于SRTP。
我不是专家,就像你一样撞墙......
答案 2 :(得分:3)
目前尚不清楚这是否属于您的情况,但请注意,不可能从SRTP仅仅是被动观察者的角度访问音频/视频(即:nncrypt) - 这就是传输加密的重点。
协议(DTLS-SRTP)大致如下:
如果您无法访问密钥对的至少一个私有部分,则根本无法解密连接。如果端点选择在握手时使用Diffie-Hellman key exchange,则被动攻击者将无法获取派生密钥,即使访问两个私钥也是如此。此属性称为forward secrecy。
访问SRTP内容的唯一可靠方法是自己进行握手,实现活动MITM(更改SDP上的指纹)或从浏览器获取私钥并限制DH密钥交换(其中,AFAIK,是根本不可能)