ZRTP交叉编译与移植

1 ZRTP源码下载

这里采用的是libzrtp来自于freeswitch:libs/libzrtp。

2 ZRTP交叉编译

zrtp编译比较简单,采用configure进行编译在根目录心中zrtp编译脚本,只需要指定交叉编译工具链和安装地址即可。脚本如下所示:

unset CC CFLAGS LDFLAGS CPPFLAGS CPP LD STRIP
./configure --host=arm-linux-androideabi --prefix=`pwd`/../objects/ 

成果物如下所示include和lib库:
在这里插入图片描述
在这里插入图片描述

3 ZRTP移植

zrtp移植主要对zrtp库进行封装,对外提供初始化和加密解密能力。接口设计如下:

3.1 API设计

typedef void ZrtpEventObserver(int id, BOOL encrypt);typedef struct zrtp_handle_t zrtp_handle_t;typedef struct zrtp_handle_t{//加密rtpvoid (*encrypt_rtp)(zrtp_handle_t *pthis, int channel, unsigned char* in_data,unsigned char* out_data,int bytes_in,	int* bytes_out);//解密rtpvoid (*decrypt_rtp)(zrtp_handle_t *pthis, int channel, unsigned char* in_data, unsigned char* out_data, int bytes_in, int* bytes_out);//加密rtcpvoid (*encrypt_rtcp)(zrtp_handle_t *pthis, int channel, unsigned char* in_data,unsigned char* out_data, int bytes_in,int* bytes_out);//解密rtcpvoid (*decrypt_rtcp)(zrtp_handle_t *pthis, int channel, unsigned char* in_data, unsigned char* out_data, int bytes_in, int* bytes_out);BOOL (*is_enabled)(zrtp_handle_t *pthis);void *priv;
}zrtp_handle_t;//构建zrtp会话
int zrtp_handle_alloc(zrtp_handle_t **ppthis, const WebRtc_Word32 id, ZrtpEventObserver *observer);
//释放zrtp会话
void zrtp_handle_free(zrtp_handle_t *pthis);
//初始化
int zrtp_handle_init();
//反初始化
void zrtp_handle_denit();

3.2 初始化

初始化只需要初始化一次,初始化需要注册发送回调函数,这里协商发送的数据包构造好后最终是有这个接口on_send_packet返回到应用发送。

int zrtp_handle_init()
{zrtp_config_defaults(&g_zrtp_config);zrtp_randstr2((unsigned char *)g_zrtp_config.client_id, sizeof(zrtp_client_id_t));
//	zrtp_randstr2((unsigned char *)g_zrtp_config.zid, sizeof(zrtp_zid_t));g_zrtp_config.lic_mode = ZRTP_LICENSE_MODE_ACTIVE;g_zrtp_config.cb.misc_cb.on_send_packet			= on_send_packet;g_zrtp_config.cb.event_cb.on_zrtp_protocol_event	= on_zrtp_protocol_event;g_zrtp_config.cb.event_cb.on_zrtp_security_event	= on_zrtp_security_event;g_zrtp_config.cb.event_cb.on_zrtp_secure			= on_zrtp_secure;g_zrtp_config.cb.event_cb.on_zrtp_not_secure		= on_zrtp_not_secure;zrtp_status_t s = zrtp_init(&g_zrtp_config, &g_pzrtp_global);if (zrtp_status_ok != s) {printf("ZRTP init failed, status = %d \n", s);return -1;}return 0;
}void zrtp_handle_denit()
{if (NULL != g_pzrtp_global) {zrtp_down(g_pzrtp_global);g_pzrtp_global = NULL;}
}

3.3 会话实例

每一路会话需要实例化一个zrtphandle对象,需要传入一个随机的zrtpid,和观察者。

int zrtp_handle_alloc(zrtp_handle_t **ppthis, const WebRtc_Word32 id, ZrtpEventObserver *observer)
{if(!ppthis)return -1;      zrtp_handle_t *phl = (zrtp_handle_t *)malloc(sizeof(zrtp_handle_t));	if(!phl){return -1;}priv_t *ppriv = (priv_t *)malloc(sizeof(priv_t));	if(!ppriv){free(phl);return -1;}memset(phl, 0, sizeof(zrtp_handle_t));memset(ppriv, 0, sizeof(priv_t));phl->priv = ppriv;   ppriv->__zrtp_session = NULL;ppriv->__zrtp_audio = NULL;ppriv->__lSSRC = 0;ppriv->__rSSRC = 0;ppriv->__stream_seq = 0;ppriv->__stream_timestamp = 0;ppriv->__is_first_start_stream = 0;ppriv->__is_need_send_hello = 0;ppriv->__is_zrtp_enable = 0;ppriv->__obverserptr = observer;ppriv->id = id;ppriv->__buffer_out_data = (char *)malloc(IP_PACKET_SIZE);phl->audio_encrypt_rtp = encrypt;phl->audio_decrypt_rtp = decrypt;phl->audio_encrypt_rtcp = encrypt_rtcp;phl->audio_decrypt_rtcp = decrypt_rtcp;*ppthis = phl;return 0;
}void zrtp_handle_free(zrtp_handle_t *pthis) 
{if(!pthis)return;DisableZsrtp(pthis);priv_t *ppriv = pthis->priv;if (NULL != ppriv->__buffer_out_data) {free(ppriv->__buffer_out_data);ppriv->__buffer_out_data = NULL;}if (pthis->priv){free(pthis->priv);pthis->priv = NULL;}	free(pthis);pthis = NULL;
}

3.4 加解密实现

加解密会用首先会进入到协商流程zrtp_stream_start完成协商,之后再进入加解密流程zrtp_process_rtp。

int encrypt(zrtp_handle_t *pthis,int channel,unsigned char* in_data,unsigned char* out_data,int bytes_in,int* bytes_out) {priv_t *ppriv = pthis->priv;if (!ppriv->__is_zrtp_enable || NULL == in_data || NULL == out_data|| 0 > bytes_in || NULL == bytes_out) {// invalidreturn 0;}if(ppriv->__is_need_send_hello){zrtp_stream_start(ppriv->__zrtp_audio, ppriv->__lSSRC);ppriv->__is_need_send_hello = RL_FALSE;}if(!ppriv->__buffer_out_data_consumed){++ppriv->__buffer_out_data_retry;memcpy(out_data, ppriv->__buffer_out_data, ppriv->__buffer_out_data_bytes);*bytes_out = ppriv->__buffer_out_data_bytes;ppriv->__buffer_out_data_consumed = RL_TRUE;return 0;}if (-1 == ppriv->__voice_encrypt_status && ppriv->__buffer_out_data_retry == ZRTP_COUNT_THRESHOLD_DEFAULT){// LinKy: Rollback to unecrypt, this operation will close zrtp session!UpdateEncryptStatus(pthis, RL_FALSE);//return 0;}if (ppriv->__zrtp_audio->state != ZRTP_STATE_SECURE) {// Not ready, use original data	memcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;return 1;}char packet[IP_PACKET_SIZE];ZRTP_UNALIGNED(zrtp_rtp_hdr_t) *rtp_hdr = (zrtp_rtp_hdr_t*)packet;/* Fill RTP Header according to the specification */zrtp_memset(rtp_hdr, 0, sizeof(zrtp_rtp_hdr_t));rtp_hdr->version = 2;						/* Current RTP version 2 */rtp_hdr->pt = 0;							/* PCMU padding type */rtp_hdr->ssrc = zrtp_hton32(ppriv->__lSSRC);		/* Use stream Identifier as it's SSRC */if (ppriv->__stream_seq >= 0xFFFF) {ppriv->__stream_seq = 0;}rtp_hdr->seq = libzrtp_swap16(ppriv->__stream_seq++);rtp_hdr->ts = zrtp_hton32(ppriv->__stream_timestamp);ppriv->__stream_timestamp += 20;					// LinKy: Assume the interval is 20mszrtp_memcpy(packet + sizeof(zrtp_rtp_hdr_t), in_data, bytes_in);unsigned int size = sizeof(zrtp_rtp_hdr_t) + bytes_in;zrtp_status_t s = zrtp_process_rtp(ppriv->__zrtp_audio, packet, &size);switch (s) {case zrtp_status_ok: {//// Packet was successfully decrypted. Dont forget that packet// size was changed during decryption. New size now in size //memcpy(out_data, packet, size);*bytes_out = size;return 2;}break;case zrtp_status_drop: {//// This is a protocol ZRTP packet or masked RTP media.// In either case the packet must be dropped to protect your // private data and media codec// LinKy: Shall we rollback to unencrypt here?return 3;}break;case zrtp_status_fail: {//// This is some kind of error - see logs for more information.// Don't put such packet to the network. It is not secure.//memcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;return 4;}break;}return 0;
}int decrypt(zrtp_handle_t *pthis,int channel,unsigned char* in_data,unsigned char* out_data,int bytes_in,int* bytes_out) {unsigned int size = bytes_in;priv_t *ppriv = pthis->priv;if (!ppriv->__is_zrtp_enable || NULL == in_data || NULL == out_data|| 0 > bytes_in || NULL == bytes_out) {// invalidreturn 0;}if(ppriv->__is_need_send_hello){zrtp_stream_start(ppriv->__zrtp_audio, ppriv->__lSSRC);ppriv->__is_need_send_hello = RL_FALSE;}//if zrtp success,ppriv->__buffer_in_data_retry Approximately equals 18;if (-1 == ppriv->__voice_encrypt_status && ppriv->__buffer_in_data_retry >= ZRTP_COUNT_THRESHOLD_DEFAULT){//if (ppriv->__zrtp_audio->state != ZRTP_STATE_SECURE){// Not ready, use original datamemcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;return 1;}else if(ppriv->__voice_encrypt_status == 0){memcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;return 1;}ppriv->__buffer_in_data_retry++;char packet[IP_PACKET_SIZE];memcpy(packet, in_data, bytes_in);zrtp_status_t s = zrtp_process_srtp(ppriv->__zrtp_audio, packet, &size);switch (s) {case zrtp_status_ok: {//// Packet was successfully decrypted. Dont forget that packet// size was changed during decryption. New size now in size //char *body = packet + sizeof(zrtp_rtp_hdr_t);memcpy(out_data, body, size - sizeof(zrtp_rtp_hdr_t));*bytes_out = size - sizeof(zrtp_rtp_hdr_t);return 2;}break;case zrtp_status_drop: {//// This is a protocol ZRTP packet or masked RTP media.// In either case the packet must be dropped to protect your // private data and media codec// LinKy: Yep, we drop it, use original data to play!memcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;return 3;}break;case zrtp_status_fail: {//// This is some kind of error - see logs for more information.// Don't put such packet to the network. It is not secure.//// LinKy: Be careful! This may cause noise if data is encrypted actually!memcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;return 4;}break;}return 0;
}void encrypt_rtcp(zrtp_handle_t *pthis,int channel,unsigned char* in_data,unsigned char* out_data,int bytes_in,int* bytes_out) {priv_t *ppriv = pthis->priv;unsigned int size = bytes_in;if (!ppriv->__is_zrtp_enable || NULL == in_data || NULL == out_data|| 0 > bytes_in || NULL == bytes_out) {// invalidreturn;}if(ppriv->__is_need_send_hello){zrtp_stream_start(ppriv->__zrtp_audio, ppriv->__lSSRC);ppriv->__is_need_send_hello = RL_FALSE;}if (ppriv->__zrtp_audio->state != ZRTP_STATE_SECURE) {// Not ready, use original datamemcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;return;}char packet[IP_PACKET_SIZE];ZRTP_UNALIGNED(zrtp_rtcp_hdr_t) *rtcp_hdr = (zrtp_rtcp_hdr_t*)packet;/* Fill RTCP Header according to the specification */rtcp_hdr->rc = 0;rtcp_hdr->version = 2;rtcp_hdr->ssrc = zrtp_hton32(ppriv->__lSSRC);/* Get RTP body from PGP words lists. Put RTCP marker at the beginning */zrtp_memcpy(packet + sizeof(zrtp_rtcp_hdr_t), "RTCP", 4);		zrtp_memcpy(packet + sizeof(zrtp_rtcp_hdr_t) + 4, in_data, bytes_in);size = sizeof(zrtp_rtcp_hdr_t) + bytes_in + 4;/* RTCP packets sould be 32 byes aligned */size += (size % 4) ? (4 - size % 4) : 0;zrtp_status_t s = zrtp_process_rtcp(ppriv->__zrtp_audio, packet, &size);switch (s) {case zrtp_status_ok: {//// Packet was successfully decrypted. Dont forget that packet// size was changed during decryption. New size now in size //memcpy(out_data, packet, size);*bytes_out = size;}break;case zrtp_status_drop: {//// This is a protocol ZRTP packet or masked RTP media.// In either case the packet must be dropped to protect your // private data and media codec// LinKy: Shall we rollback to unencrypt here?}break;case zrtp_status_fail: {//// This is some kind of error - see logs for more information.// Don't put such packet to the network. It is not secure.//memcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;}break;}
}void decrypt_rtcp(zrtp_handle_t *pthis,int channel,unsigned char* in_data,unsigned char* out_data,int bytes_in,int* bytes_out) {priv_t *ppriv = pthis->priv;unsigned int size = bytes_in;if (!ppriv->__is_zrtp_enable || NULL == in_data || NULL == out_data|| 0 > bytes_in || NULL == bytes_out) {// invalidreturn;}if(ppriv->__is_first_start_stream){zrtp_stream_start(ppriv->__zrtp_audio, channel);ppriv->__is_first_start_stream = RL_FALSE;}if (ppriv->__zrtp_audio->state != ZRTP_STATE_SECURE) {// Not ready, use original datamemcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;return;}char packet[IP_PACKET_SIZE];memcpy(packet,in_data,bytes_in);zrtp_status_t s = zrtp_process_srtcp(ppriv->__zrtp_audio, packet, &size);switch (s) {case zrtp_status_ok: {//// Packet was successfully decrypted. Dont forget that packet// size was changed during decryption. New size now in size //char *body = packet + sizeof(zrtp_rtp_hdr_t);memcpy(out_data, body, size - sizeof(zrtp_rtp_hdr_t));*bytes_out = size - sizeof(zrtp_rtp_hdr_t);}break;case zrtp_status_drop: {//// This is a protocol ZRTP packet or masked RTP media.// In either case the packet must be dropped to protect your // private data and media codec// LinKy: Yep, we drop it, use original data to play!memcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;}break;case zrtp_status_fail: {//// This is some kind of error - see logs for more information.// Don't put such packet to the network. It is not secure.//// LinKy: Be careful! This may cause noise if data is encrypted actually!memcpy(out_data, in_data, bytes_in);*bytes_out = bytes_in;}break;}
}

4 ZRTP抓包分析

一个完整的ZRTP协商流程,首先是hello进双方加密方式的交换,之后会进行一个收到的应答,然后是commit消息确认HMAC秘钥,DHPart消息交换公钥,Confirm消息确认签名,最后是ConfACK应答。下面是wareshark抓包显示的交互流程。
在这里插入图片描述

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

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

相关文章

三一充填泵:煤矿矸石无害化充填,煤炭绿色高效开采的破局利器

富煤贫油少气是我国的能源禀赋特征,决定了我国以煤炭为主的能源结构,煤炭为国民经济发展提供了重要的基础。煤炭开采过程会对土地、地下水、空气等环境造成较大的污染,但大宗固废煤矸石无害化充填的技术手段可以有效改善这样的情况&#xff0…

《视觉 SLAM 十四讲》V2 第 6 讲 非线性优化 【高斯牛顿法、列文伯格-马夸尔特方法 、Ceres 库 和 g2o库 】

文章目录 6.1.2 最小二乘 寻找下降增量 Δ x k \Delta\bm{x}_k Δxk​的 4 种方法6.2.1 一阶和二阶梯度法(最速下降法、牛顿法)6.2.2 高斯牛顿法6.2.3 列文伯格-马夸尔特方法 【阻尼牛顿法】【信赖区域法】 6.3 实践6.3.1 手写高斯牛顿法 【Code】6.3.2 谷歌的优化库 Ceres 【最…

计算机专业毕业设计项目推荐12-志愿者管理系统(Spring+Js+Mysql)

志愿者管理系统(SpringJsMysql) **介绍****各部分模块实现** 介绍 本系列(后期可能博主会统一为专栏)博文献给即将毕业的计算机专业同学们,因为博主自身本科和硕士也是科班出生,所以也比较了解计算机专业的毕业设计流程以及模式,在编写的过程…

【进阶C语言】排序函数(qsort)与模拟实现(回调函数的实例)

本章大致内容目录: 1.认识回调函数 2.排序函数qsort 3.模拟实现qsort 回调函数为C语言重要知识点,以函数指针为主要知识;下面介绍回调函数的定义、回调函数的库函数举例即库函数模拟实现。 一、回调函数 1.回调函数定义 回调函数就是一…

ZRTP协议与原理

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

基于FastAPI的文件上传和下载

基于FastAPI的文件上传和下载 一、前言 为了实现ASR的可视化界面,在各个博客中寻觅了一波找找文件上传和下载的例子,没有找到能完整实现这个功能的,有也只是有一部分(菜菜求捞捞),看了甚是烦恼&#xff0…

数据结构刷题训练——二叉树篇(一)

📙作者简介: 清水加冰,目前大二在读,正在学习C/C、Python、操作系统、数据库等。 📘相关专栏:C语言初阶、C语言进阶、C语言刷题训练营、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 &#x1f44d…

SaaS 电商设计 (二) 全链路解决方案概述和核心业务流程梳理

一.业务目标&技术目标 业务目标:完成多业态,多渠道的数字化运营 自有业务: O2O,B2C,B2B2C,S2B2b 平台业务:POPB2c,POPB2b,POPS2B2b 1.1 自有业务 O2O:全称Online to Offline.泛指的线上线下的业务融合.这种的情况分为两种情况,第一种通过线上的数字化运营引导线上用户线下…

AutoGen - 多个Agent开发LLM应用的框架

文章目录 关于安装使用关于 Enable Next-Gen Large Language Model Applications 用多个Agent开发LLM应用的框架,这些agent可相互交流以解决任务。 官网:https://microsoft.github.io/autogen/github : http://github.com/microsoft/autogendiscord : https://discord.com/i…

Flink的处理函数——processFunction

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

vue +element 批量删除

1.拿到当前勾选状态 在el-table里边去写 单选用第一个 多选用第二个 select"selectHandle" :当用户手动勾选数据行的 Checkbox 时触发的事件 select-all"selectHandle":当用户手动勾选全选 Checkbox 时触发的事件// 点击勾选选择器selectHandle(selection…

华为云云耀云服务器L实例评测|云耀云服务器L实例部署DjangoBlog个人博客系统

华为云云耀云服务器L实例评测|云耀云服务器L实例部署DjangoBlog个人博客系统 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点 二、DjangoBlog介绍2.1 DjangoBlog介绍2.2 DjangoBlog特点 三、本次实践介绍3.1 本次实践简介3.2 本次环…

【2023双非保研】信管跨保计算机大类的记录(东南、川大、重大、东北、西电、南理工、杭高院、河海、东华、天大等)

以此篇博客记录我的保研之旅 目录 一、个人情况 二、夏令营 1、国科大杭高院(线下) 2、南信工(线下) 3、华中师范(线上or线下) 4、浙大软件(线上) 5、东华大学(线…

哈希应用之位图

文章目录 1.位图概念2.面试题引入3.代码解决[配注释]4.位图应用4.1找到100亿个整数里只出现一次的整数4.2找两个分别有100亿个整数的文件的交集[只有1G内存]1.法一[使用于数据量<42亿]2.法二[适用于数据量大>42亿]3.在一个有100亿个int的文件中找到出现次数不超过2次的所…

假期AI新闻热点:亚运会Al技术亮点;微软GPT-4V论文精读;Perplexity推出pplx-api;DALL-E 3多渠道测评 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f525; 科技感拉满&#xff0c;第19届杭州亚运会中的Al技术亮点 八年筹备&#xff0c;杭州第19届亚运会开幕式于9月23日晚隆重举行&#xff0…

vue3中使用return语句返回this.$emit(),在同一行不执行,换行后才执行,好奇怪!

今天练习TodoList任务列表案例,该案例效果如图所示&#xff1a; 此案例除了根组件App.vue&#xff0c;还有TodoList、TodoInput、TodoButton三个子组件。 因为有视频讲解&#xff0c;在制作TodoList、TodoInput时很顺利&#xff0c;只是在完成TodoButton这个组件时出了点问题…

<二>Qt斗地主游戏开发:过场动画的实现

1. 过场动画效果 2. 思路分析 过场动画较为简单&#xff0c;只有一个进度条在进行滚动&#xff0c;因此实现起来不需要动画相关处理&#xff0c;仅需要图片和定时器设定&#xff0c;让进度条动起来即可。我们可以创建一个对话框&#xff0c;设定背景图片以及对话框透明无边框&a…

口袋参谋:如何有效地监测你的竞争对手!

​在淘宝天猫上开店&#xff0c;竞争是非常大的&#xff0c;那么就会出现许多同样的产品&#xff0c;如果想要在竞争中胜出&#xff0c;就需要多去研究同行的数据&#xff0c;知己知彼&#xff0c;百战百胜。 掌握竞争对手数据目的主要是有2个&#xff1a; 1、掌握对手是怎么起…

操作符 | C语言中操作符详解 | 操作符的优先级 | 移位操作法的使用方式

一、算术操作符&#xff1a;、-、*、/、% 算术操作符其实在平时生活中&#xff0c;也遇到很多&#xff0c;并且这五类操作符基本很常见&#xff0c;而他们的作用与数学所学习的功能是一样的。但是“/”除号操作符与“%”取模操作符有些不同。下面就以这两个的操作符为主要说起…

伟大不能被计划

假期清理书单&#xff0c;把这个书读完了&#xff0c;结果发现出奇的好&#xff0c;可以说是值得亲身去读的书&#xff0c;中间的一些论述提供了人工智能专业方面的视角来论证这这个通识观点&#xff0c;可信度很不错&#xff1b; 这篇blog也不是对书的总结&#xff0c;更多的是…