注:以下为rfc5764的学习笔记,不保证完全正确。

DTLS-SRTP是DTLS的一个扩展,将SRTP加解密与DTLS的key交换和会话管理相结合。从SRTP的角度看,是为其提供一种新的key协商管理的方法;从DTLS的角度看,是为应用数据提供一个新的数据格式(SRTP/SRTCP)。

1,应用层数据加解密是由SRTP完成的,要求必须是RTP/RTCP的格式。
2,DTLS的握手过程是为SRTP加解密过程协商使用哪种profile和密钥。
3,除了应用数据加密为SRTP格式,其他record-layer的报文仍为普通的DTLS格式(比如TLS control message)
4,当发送SRTP格式的应用层数据时,需要直接跳过DTLS加密层,将SRTP数据包透传到下层的数据传输层做发送。

由于密钥和加密参数是在DTLS握手过程中协商得到的,而此过程是保密的,因而相比常规的方式(比如在通过SDP消息交互来协商)更为安全。在发起DTLS握手之前,需要先设置use-srtp扩展。

接收端使用 DTLS-SRTP
自DTLS下层的传输层收到报文之后,需要根据包头特征手动区分做demultiplexing,一般可以如下进行
检查第一个报文的第一个字节
1,是[0, 1]时,表示可能是STUN报文
2,是[128, 191]时,表示可能时RTP(SRTP)报文
3,是[20, 63]时,表示可能是DTLS record layer报文
其他的类别请根据实际情况做区分处理

DTLS握手成功之后,需要导出key material,然后从中分离出server/client端用于SRTP对称加密的密钥。key material中对应SRTP的密钥,构成如下

client_master_key server_master_key client_salt server_salt

其中 master_key 和 salt 的长度是根据最终协商的 SRTP 的profile来确定的,具体可查 RFC3711 SRTP

key material导出的规范见 RFC5705 Keying Material Exporters for TLS

webrtc中对此代码实现见,webrtc/pc/channel.cc中 BaseChannel::SetupDtlsSrtp_n() 函数

Code Sample using DTLS-SRTP

 #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 * + SRTP_MASTER_KEY_SALT_LEN * ];
  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 = ;   /*
   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,
                                    ,
                                    PJ_FALSE);   memcpy(&client_write_key[], &dtls_buffer[offset], SRTP_MASTER_KEY_KEY_LEN);
  offset += SRTP_MASTER_KEY_KEY_LEN;
  memcpy(&server_write_key[], &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();
  }
  policy.ssrc.value = ;
  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");
  } }

dtls_srtp学习笔记的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

随机推荐

  1. 无线渗透测试之wifi密码破解

    [声明]:本文仅供个人学习使用,请勿违法破解他人wifi 测试工具: 1.CDlinux启动盘:(请参照https://my.oschina.net/u/3112136/blog/800713) 2. ...

  2. POJ 1873 The Fortified Forest [凸包 枚举]

    The Fortified Forest Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 6400   Accepted: 1 ...

  3. C#开发短信发送

    //需要用到的命名空间 using System.Net;using System.IO;using System.Text;//调用时只需要把拼成的URL传给该函数即可.判断返回值即可public ...

  4. Properties工具类

    /** * 加载Properties文件 * @param path Properties文件路径 * @return */ private static Properties getClasspat ...

  5. Node.js爬取豆瓣数据

    一直自以为自己vue还可以,一直自以为webpack还可以,今天在慕课逛node的时候,才发现,自己还差的很远.众所周知,vue-cli基于webpack,而webpack基于node,对node不了 ...

  6. HashMap原理阅读

    前言 还是需要从头阅读下HashMap的源码.目标在于更好的理解HashMap的用法,学习更精炼的编码规范,以及应对面试. 它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而 ...

  7. MySQL Server 5.0安装教程

    相信很多朋友刚开始接触mysql数据库服务器,下面是mysql的安装教程,步骤明细也有详细的说明. 工具/原料   mysql MySQL安装的图解   1 打开下载的mysql安装文件mysql-5 ...

  8. MysqL错误之_ERROR! MySQL server PID file could not be found!

    在配置Mysql主从GTID模式下,启动Mysql服务时出现报错,搜索了一番,找到了一个简单可靠的方法,直接成功.如果遇到相同问题没有解决的童鞋,那就去试一下很多其他方案,如,强制杀掉进程重启,修改其 ...

  9. 关于Mysql5.7高版本group by新特性报错

    一个项目的开发到测试上线运营,团队对项目的管理不成熟会影响项目的开发效率.由于项目是我刚接手,独自在Centos搭建PHP环境,所以就考虑使用高版本,选择了Mysql5.7,本地开发环境还是Windo ...

  10. UVA1213

    先打表,再回溯+剪枝 AC代码: #include<cstdio> #include<cstring> #include<cmath> const int maxn ...