深入研究websocket直播中signature这个参数怎么来的,模拟自己生成一个

上一节课我们已经找到了生成signature这个字段的代码位置,就是这个B函数,嗯......听起来好像有点奇怪,但是它确实叫B啊,笑死。不管了,看一下里面的逻辑是啥。

注意e参数的内容是:

{"app_name": "douyin_web","version_code": "180800","webcast_sdk_version": "1.0.14-beta.0","update_version_code": "1.0.14-beta.0","compress": "gzip","device_platform": "web","cookie_enabled": true,"screen_width": 1512,"screen_height": 982,"browser_language": "zh-CN","browser_platform": "MacIntel","browser_name": "Mozilla","browser_version": "5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36","browser_online": true,"tz_name": "Asia/Shanghai","cursor": "t-1718942296076_r-1_d-1_u-1_h-7382800685396382772","internal_ext": "internal_src:dim|wss_push_room_id:7382777844734167858|wss_push_did:7347516590731134502|first_req_ms:1718942295989|fetch_time:1718942296076|seq:1|wss_info:0-1718942296076-0-0|wrds_v:7382800932146251064","host": "https://live.douyin.com","aid": "6383","live_id": 1,"did_rule": 3,"endpoint": "live_pc","support_wrds": 1,"user_unique_id": "7347516590731134502","im_path": "/webcast/im/fetch/","identity": "audience","need_persist_msg_count": "15","insert_task_id": "","live_reason": "","room_id": "7382777844734167858","heartbeatDuration": "0"
}

注意t是很多参数的e里面的websocket_key数组,它里面是:

[{param_name: 'live_id',param_type: 'string',},{param_name: 'aid',param_type: 'string',},{param_name: 'version_code',param_type: 'string',},{param_name: 'webcast_sdk_version',param_type: 'string',},{param_name: 'room_id',param_type: 'string',},{param_name: 'sub_room_id',param_type: 'string',},{param_name: 'sub_channel_id',param_type: 'string',},{param_name: 'did_rule',param_type: 'string',},{param_name: 'user_unique_id',param_type: 'string',},{param_name: 'device_platform',param_type: 'string',},{param_name: 'device_type',param_type: 'string',},{param_name: 'ac',param_type: 'string',},{param_name: 'identity',param_type: 'string',},]

有了这两个参数传递过来,那我们就可以安心研究B里面的逻辑了。

看一下这个for循环吧,它的逻辑就是取出e里面的参数(将t里面的参数名称),然后拼接到o这个字符串上,然后再把o传递给V()这个函数:

V()这个函数里面又做了什么事情呢?V()其实会返回一个函数,这个函数可以传递两个参数,

接下来继续看返回的这个函数里面代码逻辑: 

其实这里继续深入研究,会发现是把e参数转为Bytes数组了:

这个转换函数也可以自己写一个:

        const o =',live_id=1,aid=6383,version_code=180800,webcast_sdk_version=1.0.14-beta.0,room_id=7382777844734167858,sub_room_id=,sub_channel_id=,did_rule=3,user_unique_id=7347516590731134502,device_platform=web,device_type=,ac=,identity=audience'const substr = o.substring(1)console.log('subStr----', substr)// 将字符串转Bytes数组const stringToBytes = (str) => {var array = new Uint8Array(str.length)for (var i = 0, l = str.length; i < l; i++) {array[i] = str.charCodeAt(i)}return array}console.log('字符串转为Bytes数组', stringToBytes(substr))

转换完之后,又使用wordsToBytes函数将结果转成了另外一个形式:

然后再调用bytesToHex函数:

const bytesToHex = function (e) {for (var t = [], r = 0; r < e.length; r++)t.push((e[r] >>> 4).toString(16)), t.push((15 & e[r]).toString(16))return t.join('')
}

转换之后的结果格式为:a5faced0e2965a966b9fde2044e3ff1e

然后再调用frontierSign函数将上面这串字符串转为signature的值:

但是这个frontierSign是啥呢?这是一个webmssdk.es5.js包里面的函数,所以需要将这个webmssdk.es5.js包下载到本地,然后集成到window对象上,就可以调用这个函数了,我这里写了一个demo:可以看到已经生成了值

demo代码如下:

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><script src="./vFun.js"></script><script src="./webmssdk.es5.js"></script></head><body><div>测试代码</div></body><script>const config = [{param_name: 'live_id',param_type: 'string',},{param_name: 'aid',param_type: 'string',},{param_name: 'version_code',param_type: 'string',},{param_name: 'webcast_sdk_version',param_type: 'string',},{param_name: 'room_id',param_type: 'string',},{param_name: 'sub_room_id',param_type: 'string',},{param_name: 'sub_channel_id',param_type: 'string',},{param_name: 'did_rule',param_type: 'string',},{param_name: 'user_unique_id',param_type: 'string',},{param_name: 'device_platform',param_type: 'string',},{param_name: 'device_type',param_type: 'string',},{param_name: 'ac',param_type: 'string',},{param_name: 'identity',param_type: 'string',},]// 使用for便利试试for (let { param_name: i } of config) {console.log('i----', i)}const o =',live_id=1,aid=6383,version_code=180800,webcast_sdk_version=1.0.14-beta.0,room_id=7382772251994655488,sub_room_id=,sub_channel_id=,did_rule=3,user_unique_id=7347516590731134502,device_platform=web,device_type=,ac=,identity=audience'const substr = o.substring(1)console.log('subStr----', substr)// s函数就是stringToBytesconst sResult = sFunc(substr)//  V()函数就是console.log('s函数stringToBytes结果', sResult)// 有了s的返回结果,再调用i.wordsToBytes// var r = i.wordsToBytes(s(e, t));const r = wordsToBytes(sResult)console.log('r----', r)// 最后调用bytesToHex;// return t && t.asBytes ? r : t && t.asString ? a.bytesToString(r) : i.bytesToHex(r)const bytesRes = bytesToHex(r)console.log('bytesRes----', bytesRes)const frontierSignRes = window.byted_acrawler.frontierSign({'X-MS-STUB': bytesRes,})console.log('frontierSignRes----', frontierSignRes)</script>
</html>

vFun.js的代码如下:

var sFunc = function (e, t) {// 判断e是不是string类型,是的话,把t赋值给e,然后e.constructor == String? stringToBytes(e): oFunc(e)? (e = Array.prototype.slice.call(e, 0)): Array.isArray(e) || e.constructor === Uint8Array || (e = e.toString())for (var r = bytesToWords(e),l = 8 * e.length,c = 1732584193,u = -271733879,p = -1732584194,d = 271733878,h = 0;h < r.length;h++)r[h] =(((r[h] << 8) | (r[h] >>> 24)) & 16711935) |(((r[h] << 24) | (r[h] >>> 8)) & 4278255360);(r[l >>> 5] |= 128 << l % 32), (r[(((l + 64) >>> 9) << 4) + 14] = l)for (var m = sff, f = sgg, g = shh, _ = sii, h = 0; h < r.length; h += 16) {var v = c,C = u,y = p,T = d;(c = m(c, u, p, d, r[h + 0], 7, -680876936)),(d = m(d, c, u, p, r[h + 1], 12, -389564586)),(p = m(p, d, c, u, r[h + 2], 17, 606105819)),(u = m(u, p, d, c, r[h + 3], 22, -1044525330)),(c = m(c, u, p, d, r[h + 4], 7, -176418897)),(d = m(d, c, u, p, r[h + 5], 12, 1200080426)),(p = m(p, d, c, u, r[h + 6], 17, -1473231341)),(u = m(u, p, d, c, r[h + 7], 22, -45705983)),(c = m(c, u, p, d, r[h + 8], 7, 1770035416)),(d = m(d, c, u, p, r[h + 9], 12, -1958414417)),(p = m(p, d, c, u, r[h + 10], 17, -42063)),(u = m(u, p, d, c, r[h + 11], 22, -1990404162)),(c = m(c, u, p, d, r[h + 12], 7, 1804603682)),(d = m(d, c, u, p, r[h + 13], 12, -40341101)),(p = m(p, d, c, u, r[h + 14], 17, -1502002290)),(u = m(u, p, d, c, r[h + 15], 22, 1236535329)),(c = f(c, u, p, d, r[h + 1], 5, -165796510)),(d = f(d, c, u, p, r[h + 6], 9, -1069501632)),(p = f(p, d, c, u, r[h + 11], 14, 643717713)),(u = f(u, p, d, c, r[h + 0], 20, -373897302)),(c = f(c, u, p, d, r[h + 5], 5, -701558691)),(d = f(d, c, u, p, r[h + 10], 9, 38016083)),(p = f(p, d, c, u, r[h + 15], 14, -660478335)),(u = f(u, p, d, c, r[h + 4], 20, -405537848)),(c = f(c, u, p, d, r[h + 9], 5, 568446438)),(d = f(d, c, u, p, r[h + 14], 9, -1019803690)),(p = f(p, d, c, u, r[h + 3], 14, -187363961)),(u = f(u, p, d, c, r[h + 8], 20, 1163531501)),(c = f(c, u, p, d, r[h + 13], 5, -1444681467)),(d = f(d, c, u, p, r[h + 2], 9, -51403784)),(p = f(p, d, c, u, r[h + 7], 14, 1735328473)),(u = f(u, p, d, c, r[h + 12], 20, -1926607734)),(c = g(c, u, p, d, r[h + 5], 4, -378558)),(d = g(d, c, u, p, r[h + 8], 11, -2022574463)),(p = g(p, d, c, u, r[h + 11], 16, 1839030562)),(u = g(u, p, d, c, r[h + 14], 23, -35309556)),(c = g(c, u, p, d, r[h + 1], 4, -1530992060)),(d = g(d, c, u, p, r[h + 4], 11, 1272893353)),(p = g(p, d, c, u, r[h + 7], 16, -155497632)),(u = g(u, p, d, c, r[h + 10], 23, -1094730640)),(c = g(c, u, p, d, r[h + 13], 4, 681279174)),(d = g(d, c, u, p, r[h + 0], 11, -358537222)),(p = g(p, d, c, u, r[h + 3], 16, -722521979)),(u = g(u, p, d, c, r[h + 6], 23, 76029189)),(c = g(c, u, p, d, r[h + 9], 4, -640364487)),(d = g(d, c, u, p, r[h + 12], 11, -421815835)),(p = g(p, d, c, u, r[h + 15], 16, 530742520)),(u = g(u, p, d, c, r[h + 2], 23, -995338651)),(c = _(c, u, p, d, r[h + 0], 6, -198630844)),(d = _(d, c, u, p, r[h + 7], 10, 1126891415)),(p = _(p, d, c, u, r[h + 14], 15, -1416354905)),(u = _(u, p, d, c, r[h + 5], 21, -57434055)),(c = _(c, u, p, d, r[h + 12], 6, 1700485571)),(d = _(d, c, u, p, r[h + 3], 10, -1894986606)),(p = _(p, d, c, u, r[h + 10], 15, -1051523)),(u = _(u, p, d, c, r[h + 1], 21, -2054922799)),(c = _(c, u, p, d, r[h + 8], 6, 1873313359)),(d = _(d, c, u, p, r[h + 15], 10, -30611744)),(p = _(p, d, c, u, r[h + 6], 15, -1560198380)),(u = _(u, p, d, c, r[h + 13], 21, 1309151649)),(c = _(c, u, p, d, r[h + 4], 6, -145523070)),(d = _(d, c, u, p, r[h + 11], 10, -1120210379)),(p = _(p, d, c, u, r[h + 2], 15, 718787259)),(u = _(u, p, d, c, r[h + 9], 21, -343485551)),(c = (c + v) >>> 0),(u = (u + C) >>> 0),(p = (p + y) >>> 0),(d = (d + T) >>> 0)}return endian([c, u, p, d])
}// (s._blocksize = 16)
// (s._digestsize = 16)const sff = function (e, t, r, i, n, o, a) {var s = e + ((t & r) | (~t & i)) + (n >>> 0) + areturn ((s << o) | (s >>> (32 - o))) + t
}const sgg = function (e, t, r, i, n, o, a) {var s = e + ((t & i) | (r & ~i)) + (n >>> 0) + areturn ((s << o) | (s >>> (32 - o))) + t
}const shh = function (e, t, r, i, n, o, a) {var s = e + (t ^ r ^ i) + (n >>> 0) + areturn ((s << o) | (s >>> (32 - o))) + t
}const sii = function (e, t, r, i, n, o, a) {var s = e + (r ^ (t | ~i)) + (n >>> 0) + areturn ((s << o) | (s >>> (32 - o))) + t
}const stringToBytes = function (str) {var array = new Uint8Array(str.length)for (var i = 0, l = str.length; i < l; i++) {array[i] = str.charCodeAt(i)}return array
}const oFunc = function (e) {return (null != e &&(t(e) ||('function' == typeof e.readFloatLE &&'function' == typeof e.slice &&t(e.slice(0, 0))) ||!!e._isBuffer))
}const bytesToWords = function (e) {for (var t = [], r = 0, i = 0; r < e.length; r++, i += 8)t[i >>> 5] |= e[r] << (24 - (i % 32))return t
}const wordsToBytes = function (e) {for (var t = [], r = 0; r < 32 * e.length; r += 8)t.push((e[r >>> 5] >>> (24 - (r % 32))) & 255)return t
}const endian = function (e) {if (e.constructor == Number)return (16711935 & rotl(e, 8)) | (4278255360 & rotl(e, 24))for (var t = 0; t < e.length; t++) e[t] = endian(e[t])return e
}const rotl = function (e, t) {return (e << t) | (e >>> (32 - t))
}const bytesToHex = function (e) {for (var t = [], r = 0; r < e.length; r++)t.push((e[r] >>> 4).toString(16)), t.push((15 & e[r]).toString(16))return t.join('')
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flutter ffi Failed to lookup symbol

iOS release版本&#xff0c;解决方式参考官方文档&#xff1a;在 iOS 中使用 dart:ffi 调用本地代码 如果debug版本也报这个错误&#xff0c;很可能是有多个.c文件&#xff0c;编译的时候没带上&#xff01; 假设你的ffi模块名字是 c_lib 对于Android端&#xff0c;需要修改…

索引的分类和回表查询——Java全栈知识(29)

索引的分类和回表查询 Mysql 的索引按照类型可以分为以下几类&#xff0c;但是我们使用的 InnoDB 只支持主键索引&#xff0c;唯一索引&#xff0c;普通索引&#xff0c;并不支持全文索引。 1、聚集索引和二级索引 InnoDB 可以将索引分为两类分别是聚集索引和二级索引&…

java基于ssm+jsp 医院远程诊断系统

1前台首页功能模块 医院远程诊断系统&#xff0c;在系统首页可以查看首页、医生信息、论坛信息、我的、跳转到后台、客服等内容&#xff0c;如图1所示。 图1前台首页功能界面图 用户登录&#xff0c;在用户登录页面可以填写用户名、密码、等信息进行用户登录&#xff0c;如图2…

vue3滚动日历选择器

倒叙日历&#xff1a; <template><div class"date-picker"><div class"column" wheel"onYearScroll"><div v-for"(year, index) in displayedYears" :key"index" :class"{current: year current…

复分析——第7章——ζ 函数和素数定理(E.M. Stein R. Shakarchi)

第7章 ζ函数和素数定理 Bernhard Riemann, whose extraordinary intuitive powers we have already mentioned, has especially renovated our knowledge of the distribution of prime numbers, also one of the most mysterious questions in mathematics. He has tau…

uniapp实现路由拦截——遇到问题(三)

uniapp路由拦截开发过程中遇到问题 文章目录 uniapp路由拦截开发过程中遇到问题App 无法退出应用监听返回数据结构解决方式模拟原生物理返回键提示不提示&#xff0c;直接退出应用 微信小程序 登录成功返回页面报错效果图不同平台来源页面数据结构解决方式 App 无法退出应用 安…

WPF——属性

一、属性 类最初只有字段与函数&#xff0c;字段为一个变量&#xff0c;访问权限可以是private&#xff0c;protected&#xff0c;public。而将字段设为private&#xff0c;不方便外界对类数据的操作&#xff0c;但是将字段设为public又怕外界对数据进行非法操作&#xff0c;于…

SpringMVC系列十一: 文件上传与自定义拦截器

文章目录 SpringMVC文件上传基本介绍需求分析 / 图解应用实例-代码实现 自定义拦截器什么是拦截器自定义拦截器执行流程分析图自定义拦截器应用实例快速入门注意事项和细节Debug执行流程 多个拦截器多个拦截器执行流程示意图应用实例1代码实现注意事项和细节 应用实例2 作业布置…

怎么区分Boombap 制作Boombap曲子教学 boombap音乐出现的时间

Boombap音乐作为嘻哈音乐文化的重要组成部分&#xff0c;具有独特的音乐节奏、样式和情感。要理解和区分Boombap音乐&#xff0c;需要从其音乐的历史渊源、音乐特征和文化影响入手。接下来给大家介绍怎么区分Boombap&#xff0c;制作Boombap曲子教学的具体内容。 一、怎么区分B…

虚拟机配置桥接模式

背景 因为要打一些awd比赛,一些扫描工具什么的,要用到kali,就想着换成一个桥接模式 但是我看网上的一些文章任然没弄好,遇到了一些问题 前置小问题 每次点开虚拟网络编辑器的时候都没有vmnet0,但是点击更改的时候却有vmnet0 第一步: 点击更改设置 第二步: 把wmnet0删掉 …

【计算机视觉】人脸算法之图像处理基础知识(六)

图像直方图 图像直方图是描述图像中像素强度分布的一种统计图表&#xff0c;它是图像处理和计算机视觉领域中一个非常基础且重要的概念。图像直方图通常用于分析图像的亮度、对比度特性&#xff0c;以及在图像增强、阈值分割、特征提取等多种图像处理任务。 import cv2 impor…

高通安卓12-固件升级

下载步骤 第一步 格式化 「下载一次即可&#xff1b;能开机能下载的板子 忽略这一步&#xff0c;直接执行第二步即可」 QFIL工具配置为UFS类型&#xff0c;勾选Provision&#xff0c;如下图&#xff1a; Programmer选择prog_firehose_ddr.elf&#xff0c;Provision Xml选择prov…

ONLYOFFICE8.1版本桌面编辑器测评

https://www.onlyoffice.com/zh/ 随着工作方式的不断演变&#xff0c;文档编辑软件成为了我们日常工作中不可或缺的一部分。而ONLYOFFICE作为一款开源且功能丰富的办公套件&#xff0c;其最新推出的8.1版本在原有基础上进行了大量的优化与更新&#xff0c;旨在提供更流畅、更安…

无人机巡检小羊仿真

详细视频地址 仿真效果 可视化三维仿真 gazebo物理仿真 px4 飞控仿真 仿qgc简易地面站 详细视频地址

微信小程序之横向列表展示

效果图 参考微信小程序可看 代码&#xff1a; <view class"lbtClass"><view class"swiper-container"><scroll-view class"swiper" scroll-x"true" :scroll-left"scrollLeft"><block v-for"(six…

DDK电通拧紧MFC-S060控制器过流维修

一、DDK伺服拧紧轴控制器过流故障的成因 1. 电源电压过低&#xff1a;当电源电压过低时&#xff0c;控制器可能会出现过流现象。 2. 负载过大&#xff1a;当负载过大时&#xff0c;DDK电通拧紧机控制器MFC-S060的电流也会随之增大&#xff0c;可能导致过流故障。 3. 控制器内部…

低价可转债崩盘,发生了什么?

下跌不在于“出库”&#xff0c;甚至不在于“风险”。问题更多在于交易层面&#xff0c;何时能积聚更多的左侧资金并成功过渡至右侧。 低价券怎么了&#xff1f; 如果说6月初主要是小微盘品种的退市风险&#xff0c;后来是一些评级下调的品种&#xff0c;到本周&#xff0c;已…

精益思想在机器人开发中的应用体现

精益思想源于制造业&#xff0c;旨在通过消除浪费、优化流程、持续改进来提升企业竞争力。在机器人开发中&#xff0c;精益思想同样具有指导意义。它要求开发团队在需求分析、设计、制造、测试等各个环节中&#xff0c;不断追求精益求精&#xff0c;力求在降低成本的同时提升产…

仓颉编程语言入门

华为在 2024 年 6 月 21 日的华为开发者大会上&#xff0c;华为终端 BG 软件部总裁龚体正式官宣了华为自研仓颉编程语言&#xff0c;并发布了 HarmonyOS NEXT 仓颉语言开发者预览版。 仓颉编程语言文件后缀名为 .cj, 以下是第一个入门代码输出&#xff1a;你好&#xff0c;仓颉…

buuctf----firmware

- -一定不能再ubutu22进行,我是在18(血泪教训) binwalk安装 buuctf firmware(binwalk和firmware-mod-kit的使用)_buu firmware-CSDN博客 参考博客 指令 sudo apt-get update sudo apt-get install python3-dev python3-setuptools python3-pip zlib1g-dev libmagic-dev pi…