SRTP交叉编译与移植

news2025/1/20 16:24:35

1 SRTP源码下载

源码下载在github采用的库为libsrtp2.5.0:

weget https://github.com/cisco/libsrtp/archive/refs/tags/v2.5.0.tar.gz

2 SRTP交叉编译

新增交叉编译脚本,这里需要支持openssl。

./configure --host=arm-linux-androideabi --prefix=$(pwd)/object --enable-openssl crypto_LIBS="-L$(pwd)/../../third_party/openssl-1.1.0h/lib" crypto_CFLAGS="-I$(pwd)/../../third_party/openssl-1.1.0h/include" && make && make install

下面是交叉编译过程

tar -xvf libsrtp-2.5.0.tar.gz
cd libsrtp-2.5.0
touch config_android.sh
./config_android.sh
./

成果物主要包括头文件和静态库:
在这里插入图片描述

3 SRTP移植

3.1 API封装设计

API设计采用handle的实现方式,init只需要进程初始化一次。srtp_app_alloc需要每次会话创建都进行一次初始化,需要传入srtp秘钥。protect和unprotect是实时进行加解密操作。

//srtp handle
typedef struct srtp_handle_t{
	int (*protect)(void *pthis, void *rtp, size_t *pkt_octet_len);
	int (*unprotect)(void *pthis, void *audio_dat, size_t *pkt_octet_len);
	void* priv;
}srtp_handle_t;

#ifdef __cplusplus
extern "C" {
#endif
// 初始化
int srtp_app_init();
void srtp_app_denit();
//会话创建
int srtp_app_alloc(srtp_handle_t **pthis, const char *srtp_dec, const char *srtp_enc);
void srtp_app_free(srtp_handle_t *pthis);

3.2 初始化实现

初始化和反初始化,只需要在开启进程初始化一次。

int srtp_app_init()
{
	int ret = srtp_init();
	if(ret < 0)
		return -1;
	
	return 0;
}

void srtp_app_denit()
{
    srtp_shutdown();
}

3.3 会话创建实现

会话创建和销毁,需要每次建立会话都要重新创建,每次的秘钥都需要采用协商的加密和解密秘钥。

static int srtp_app_set_crypto_suites(int profile, srtp_crypto_policy_t *rtp)
{
	if(rtp == NULL)
	{
		return -1;
	}
	
	switch (profile)
	{
		case rl_srtp_profile_aes128_cm_sha1_32:
		{
			srtp_crypto_policy_set_aes_cm_128_hmac_sha1_32(rtp);
			rl_log_debug("loc srtp_profile_aes128_cm_sha1_32");
			break;
		}
		case rl_srtp_profile_aes128_cm_sha1_80:
		{
			srtp_crypto_policy_set_aes_cm_128_hmac_sha1_80(rtp);
			rl_log_debug("loc srtp_profile_aes128_cm_sha1_80");
			break;
		}
		case rl_srtp_profile_aes256_cm_sha1_32:
		{
			srtp_crypto_policy_set_aes_cm_256_hmac_sha1_32(rtp);
			rl_log_debug("loc srtp_profile_aes256_cm_sha1_32");
			break;
		}			
		case rl_srtp_profile_aes256_cm_sha1_80:
		{
			srtp_crypto_policy_set_aes_cm_256_hmac_sha1_80(rtp);
			rl_log_debug("loc srtp_profile_aes256_cm_sha1_80");
			break;
		}
	
		default:
		{
			rl_log_debug("loc policy none");
			break;
		}
	}
	return 0;
	
}

static int srtp_app_start(void *pthis, const char *srtp_dec, const char *strp_enc)
{
	rl_log_debug("SRTP start");
	srtp_config_t srtp_config_loc;
	srtp_config_t srtp_config_dist;
	srtp_handle_t *p = (srtp_handle_t *)pthis;
	
	if((!pthis || !srtp_dec || !strp_enc || strlen(srtp_dec) == 0 || strlen(strp_enc) == 0))
		return -1;
	
	srtp_handle_priv_t* priv = p->priv;
	if (!priv)
		return -1;	
	
	int ret = srtp_parse_config(strp_enc, &srtp_config_loc);
	if ( ret < 0 )
	{
		return ret;
	}
	
	ret = srtp_parse_config(srtp_dec, &srtp_config_dist);
	if ( ret < 0 )
	{
		return ret;
	}

	priv->srtp_opt = 1;	
	
	memcpy(priv->srtp_params.key_loc, srtp_config_loc.key, 30);
	memcpy(priv->srtp_params.key_dist, srtp_config_dist.key, 30);
	
	srtp_app_set_crypto_suites(srtp_config_loc.profile, &priv->srtp_params.policy_loc.rtp);
	
	priv->srtp_params.policy_loc.key = priv->srtp_params.key_loc;
	priv->srtp_params.policy_loc.next = NULL;
	
	srtp_app_set_crypto_suites(srtp_config_dist.profile, &priv->srtp_params.policy_dist.rtp);
	
	priv->srtp_params.policy_dist.ssrc.type = ssrc_any_inbound;
	priv->srtp_params.policy_dist.key = priv->srtp_params.key_dist;
	priv->srtp_params.policy_dist.next = NULL;
	rl_log_debug("srtp_create ret=%i", srtp_create(&priv->srtp_params.scall_session, 
		&priv->srtp_params.policy_dist));

	return 0;
}

static void srtp_app_stop(void *pthis)
{
	srtp_handle_t *p = (srtp_handle_t *)pthis;
	if(!pthis)
		return;
	srtp_handle_priv_t* priv = p->priv;
	if (!priv)
		return;
	
	rl_log_debug("SRTP stop\n");
	if (priv->srtp_opt > 0)
	{
		priv->srtp_opt = 0;
		
		priv->srtp_params.prev_ssrc = 0;
		rl_memset(priv->srtp_params.key_loc, 0, sizeof(priv->srtp_params.key_loc));
		rl_memset(priv->srtp_params.key_dist, 0, sizeof(priv->srtp_params.key_dist));
		rl_log_debug("srtp_dealloc ret=%i", srtp_dealloc(priv->srtp_params.scall_session)); 
	}
}

int srtp_app_alloc(srtp_handle_t **pthis, const char *srtp_dec, const char *srtp_enc)
{
	if(!pthis)
		return -1;

	srtp_handle_t* p = (srtp_handle_t*)malloc(sizeof(srtp_handle_t));
	if (p == NULL)
	{
		rl_log_err("[%s-%d] malloc failed.",__FUNCTION__, __LINE__);
		return -1;
	}
	memset(p, 0, sizeof(srtp_handle_t));
	p->protect = srtp_app_protect;
	p->unprotect = srtp_app_unprotect;

	p->priv = (srtp_handle_priv_t *)malloc(sizeof(srtp_handle_priv_t));
	if(!p->priv)
	{
		free(p);
		return -1;
	}
	memset(p->priv , 0, sizeof(srtp_handle_priv_t));
	int ret = srtp_app_start(p, srtp_dec, srtp_enc);
	if (ret != 0)
	{
		srtp_app_free(p);
		return -1;
	}

	*pthis = p;
	
	return 0;

}

void srtp_app_free(srtp_handle_t *pthis)
{
	if(!pthis)
		return;
	
	srtp_app_stop(pthis);
	
	if (pthis->priv){
		free(pthis->priv);
		pthis->priv = NULL;
	}
		
	free(pthis);

}

3.4 加解密实现

加密和解密只需要传入rtp封装后的数据和长度即可进行加解密操作,操作后数据是直接替换原数据的。

static int srtp_app_protect(void *pthis, void *rtp, size_t *pkt_octet_len)
{	
	if(!pthis || !rtp || !pkt_octet_len)
		return -1;

	int ret = 0;
	unsigned int current_ssrc;
	srtp_handle_t *p = (srtp_handle_t *)pthis;
	srtp_handle_priv_t* priv = p->priv;
	if (!priv)
		return -1;
		
	srtp_t session = priv->srtp_params.scall_session;
	if(priv->srtp_opt)
	{		
		current_ssrc = *((unsigned int *)((char *)rtp + 8));
		current_ssrc = htonl(current_ssrc);
		if(priv->srtp_params.prev_ssrc != current_ssrc) 
		{
			if (priv->srtp_params.prev_ssrc > 0 )
			{
				srtp_app_remove_stream(priv->srtp_params.scall_session, priv->srtp_params.prev_ssrc);
			}
			priv->srtp_params.policy_loc.ssrc.type = ssrc_specific;
			priv->srtp_params.policy_loc.ssrc.value = current_ssrc;
			rl_log_debug("new ssrc 0x%x, %u", current_ssrc,current_ssrc);
			srtp_app_add_stream(priv->srtp_params.scall_session, &priv->srtp_params.policy_loc);

		    priv->srtp_params.prev_ssrc = current_ssrc;
	   	}

		ret = srtp_protect(priv->srtp_params.scall_session, rtp, (int *)pkt_octet_len);
		if(ret > 0)
		{
			rl_log_err("--srtp_protect problem ret=%i", ret);
			return -1;
		}
		
	}
	return 0;
}

static int srtp_app_unprotect(void *pthis, void *audio_dat, size_t *pkt_octet_len)
{
	if(!pthis || !audio_dat || !pkt_octet_len)
		return -1;

	int ret = 0;
	srtp_handle_t *p = (srtp_handle_t *)pthis;
	srtp_handle_priv_t* priv = p->priv;
	if (!priv)
		return -1;
	
	srtp_t session = priv->srtp_params.scall_session;
	 
	if(priv->srtp_opt)
	{
		ret = srtp_unprotect(priv->srtp_params.scall_session, audio_dat, (int *)pkt_octet_len);
		if(ret > 0)
		{
			/* If the decryption fail then d'nt give this packet to DSP throw the packets */
			rl_log_err("rtp_SRtpPlRecv srtp unencryption problems ret=%i", ret);
			return -1;
		}
	}
	return 0;
}

4 SRTP抓包分析

SRTP加密后可以通过wareshark抓包看到协议部分是显示SRTP,具体如下图所示。
在这里插入图片描述
其实wareshark是通过sip协商RTP/SAVP来显示srtp的标识,所以SDP协商一定要正确。在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1064177.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于python的GUI设计

GUI设计是编程应用的一个重要载体&#xff0c;是软件开发实现的重要步骤&#xff0c;需要重要掌握&#xff0c;不管是C、JAVA、python、matlab等编程语言&#xff0c;都需要GUI界面设计来实验软件开发的前期工作&#xff0c;同时也方便按钮操作。 在设计GUI的过程中&#xff0…

ZRTP协议与原理

1 ZRTP简介 ZRTP&#xff0c;全名Z Real-time Transport Protocol&#xff0c;是一种网络协议&#xff0c;旨在为实时通信提供安全性。与其它安全协议&#xff08;如TLS和IPsec&#xff09;不同&#xff0c;ZRTP专门为实时通信设计&#xff0c;包括音频和视频通话。它是由Phil…

竞赛 深度学习 opencv python 公式识别(图像识别 机器视觉)

文章目录 0 前言1 课题说明2 效果展示3 具体实现4 关键代码实现5 算法综合效果6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习的数学公式识别算法实现 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学…

支付环境安全漏洞介绍

1、平台支付逻辑全流程分析 2、平台支付漏洞如何利用&#xff1f;买东西还送钱&#xff1f; 3、BURP抓包分析修改支付金额&#xff0c;伪造交易状态&#xff1f; 4、修改购物车参数实现底价购买商品 5、SRC、CTF、HW项目月入10W副业之路 6、如何构建最适合自己的网安学习路线 1…

netcore Polly.Core

一、安装包 <PackageReference Include"Polly.Core" Version"8.0.0" /> 二、编写重试 ResiliencePipeline pipeline new ResiliencePipelineBuilder().AddRetry(new RetryStrategyOptions{MaxRetryAttempts 2,Delay TimeSpan.FromSeconds(3),O…

竞赛 机器视觉目标检测 - opencv 深度学习

文章目录 0 前言2 目标检测概念3 目标分类、定位、检测示例4 传统目标检测5 两类目标检测算法5.1 相关研究5.1.1 选择性搜索5.1.2 OverFeat 5.2 基于区域提名的方法5.2.1 R-CNN5.2.2 SPP-net5.2.3 Fast R-CNN 5.3 端到端的方法YOLOSSD 6 人体检测结果7 最后 0 前言 &#x1f5…

Flink的处理函数——processFunction

目录 一、处理函数概述 二、Process函数分类——8个 &#xff08;1&#xff09;ProcessFunction &#xff08;2&#xff09;KeyedProcessFunction &#xff08;3&#xff09;ProcessWindowFunction &#xff08;4&#xff09;ProcessAllWindowFunction &#xff…

CSDN Markdown

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

数据中台实战(05)-如何统一管理纷繁杂乱的数据指标?

各种类型的元数据有什么用&#xff1f;跟数据中台啥关系&#xff1f; 元数据在指标管理、模型设计、数据质量和成本治理四个领域都发挥作用&#xff0c;这些领域构成数据中台OneData 数据体系。今天逐一了解元数据在上述领域的应用 1 指标管理 指标&#xff0c;一种特定类型…

【Java项目推荐之黑马头条】你的发布文章业务是怎么实现的?

前言 在学习Java的路上还是遇到了很多不错的好项目的&#xff0c;今天分享给大家&#xff0c;希望能对大家面试有所帮助&#xff01; 后续会继续推荐其他好的项目&#xff0c;这次推荐的是B站开源的视频黑马头条项目&#xff0c;来吧学会它一起去虐面试官&#xff01;&#x…

MySQL:增量备份和恢复(5)

介绍 增量备份的特点 MySQL数据库二进制日志对备份的意义 增量备份的优点是没有重复数据&#xff0c;备份量不大&#xff0c;时间短。缺点也很明显&#xff0c;需要上次完全备份及完全备份之后所有的增量备份才能恢复&#xff0c;反推恢复&#xff0c;操作较为繁琐。 Mysql没有…

buildroot添加package包

本文通过一个简单的例子介绍如何在 RK3568的buildroot/package 目录下添加一个自己的 package&#xff08;软件包&#xff09; 一、开发源码工程 首先进入/app 目录下&#xff0c;在该目录下创建一个名为“mypackage”的文件夹&#xff0c;如下所示&#xff1a;   在 mypac…

LVGL_基础控件进度条bar

LVGL_基础控件进度条bar 1、创建进度条控件 // 创建一个 bar 组件(对象)&#xff0c;他的父对象是活动屏幕对象lv_obj_t *bar lv_bar_create(lv_scr_act()); LV_LOG_USER("lv_bar_get_value(bar) %d", lv_bar_get_value(bar));/* 设置位置 */ lv_obj_center(bar);…

Linux 安装字体

1.进入/usr/share/fonts路径&#xff0c;为了方便区分新安装的字体&#xff0c;最好单独创建文件夹 2.把需要安装的字体解压到自己创建的文件夹里面&#xff0c;这里要安装Hack 字体 3.输入以下三条命令如下图所示 ####三条命令要在字体路径下执行 sudo mkfontscale sudo mkfo…

【产品设计】如何开展你的B端产品需求调研

对于B端产品来说&#xff0c;需求调研是经常做而且很重要的一件事&#xff0c;只有对需求足够了解&#xff0c;才能设计出大众所喜欢的、市场所需要的好的产品。那么&#xff0c;应该如何开始你的需求调研呢&#xff1f;需求调研的执行过程又是怎样的&#xff1f;如何对结果进行…

快排(三种单趟排序法,递归非递归算法)

快排发明者:霍尔 (Sir Charles Antony Richard Hoare) 是一位英国计算机科学家。 计算机领域的爵士——托尼霍尔(Tony Hoare)(1934年1月11日出生),英文全称Sir Charles Antony Richard Hoare,常被称为Tony Hoare或者C. A. R. Hoare,1959年博士毕业于

Java方法:重复使用的操作可以写成方法哦

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、方法的概念1、什么是方法&#xff1f;2、方法的定义3、方法调用的过程 二、方法重载1、重载的概念2、方法签名 在日常生活中…

elementui修改message消息提示颜色

/* el弹出框样式 */ .el-message {top: 80px !important;border: 0; }.el-message * {color: var(--white) !important;font-weight: 600; }.el-message--success {background: var(--themeBackground); }.el-message--warning {background: var(--gradientBG); }.el-message--…

按键精灵调用大漠插件源码例子

源码名称&#xff1a;按键精灵调用大漠插件例子源码完整备注 源码名称&#xff1a;按键精灵调用大漠插件例子源码完整备注 蓝奏下载&#xff1a;https://wwi.lanzoup.com/iuffr0riiowf 飞书网盘&#xff1a;Docs

国庆作业 day 2

select实现服务器并发 #include<myhead.h> #define ERR_MSG(msg) do{\fprintf(stderr, "__%d__:", __LINE__); \perror(msg);\ }while(0)#define PORT 8888 //端口号&#xff0c;范围1024~49151 #define IP "192.168.0.103" //本…