深入研究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.mzph.cn/bicheng/31503.shtml

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

相关文章

作业管理系统

摘 要 随着网络的发展&#xff0c;信息化时代的到来&#xff0c;在教学工作的过程中作用越来越明显&#xff0c;作业的及时发布&#xff0c;学生的及时提交&#xff0c;以及通过网上的批改和评分&#xff0c;都大大促进教学质量的发展&#xff0c;充分的利用网络来加强管理&am…

用类来实现输入和输出时间(时:分:秒)

编写程序&#xff1a; 运行结果&#xff1a; 程序分析&#xff1a; 这是一个很简单的例子。类Time中只有数据成员&#xff0c;而且它们被定义为公用的&#xff0c;因此可以在类的外面对这些成员进行操作。t1被定义为Time类的对象。在主函数中向t1对象的数据成员输入用户…

“一站式企业服务平台”的功能架构

为提升区域营商环境&#xff0c;为促进区域经济发展&#xff0c;实现资源高效配置&#xff0c;全国各区域政府及产业园区都越来越重视如何创新企业服务机制、提升企业服务水平&#xff0c;来保障区域内的企业稳定及帮扶企业高质量的发展。随着近年来大数据、人工智能等新一代信…

react项目中如何书写css

一&#xff1a;问题&#xff1a; 在 vue 项目中&#xff0c;我们书写css的方式很简单&#xff0c;就是在 .vue文件中写style标签&#xff0c;然后加上scope属性&#xff0c;就可以隔离当前组件的样式&#xff0c;但是在react中&#xff0c;是没有这个东西的&#xff0c;如果直…

【学一点儿前端】单页面点击前进或后退按钮导致的内存泄露问题(history.listen监听器清除)

今天测试分配了一个比较奇怪的问题&#xff0c;在单页面应用中&#xff0c;反复点击“上一步”和“下一步”按钮时&#xff0c;界面表现出逐渐变得卡顿。为分析这一问题&#xff0c;我用Chrome的性能监控工具进行了浏览器性能录制。结果显示&#xff0c;每次点击“上一步”按钮…

Mars3d实现汽车尾气粒子效果从汽车屁股开始发射效果

本身的汽车尾气粒子效果&#xff1a;在汽车模型的中间发射的↓↓↓↓↓↓↓↓↓↓↓ Mars3d实例中是使用transY偏移值实现汽车尾气粒子效果从汽车屁股开始发射效果&#xff1a; // 动态运行车辆的尾气粒子效果 function addDemoGraphic4(graphicLayer) {const fixedRoute new…

三星与SK海力士:以混合键合技术引领3D DRAM革新之路

在高速缓存内存&#xff08;HBM&#xff09;领域持续领跑的三星与SK海力士&#xff0c;正以混合键合技术为突破口&#xff0c;开启3D DRAM技术的新纪元。这一战略转型不仅预示着存储技术的深度革新&#xff0c;更体现了两大半导体巨头在提高集成度、优化性能与成本上的不懈追求…

如何恢复电脑硬盘删除数据?提供一套实用恢复方案

在数字化时代&#xff0c;电脑硬盘中存储的数据对于个人和企业来说都至关重要。然而&#xff0c;有时我们可能会不小心删除了一些重要文件&#xff0c;或者因为某种原因导致数据丢失。这时候&#xff0c;恢复硬盘上被删除的数据就显得尤为重要。本文将为您提供一套实用的电脑硬…

光电数鸡算法《java》

一&#xff1a;需求 题目&#xff1a;一条流水线有工位D1,D2,D3…D20,总共20个工位。 每个工位都装有一个光电计数器&#xff0c;每个工位都为本工位的计数减去前一个工位&#xff08;第一个有数值的工位除外&#xff0c;不计算。&#xff09; 计算规则&#xff1a;比如D1,D2都…

在自托管基础设施上使用 GitOps 部署 MinIO

基于MinIO Weaviate Python GitOps探索的见解&#xff0c;本文探讨了如何增强软件部署流程的自动化。 通过将 GitHub Actions 与 Docker Swarm 集成而产生的协同作用&#xff0c;以自托管基础架构的稳健性为基础&#xff0c;标志着 CI/CD 实践的关键进步。这种方法不仅利用了软…

Go语言开发框架GoFly已集成数据可视化大屏开发功能,让开发者只专注业务开发,本文指导大家如何使用

前言 框架提供数据大屏开发基础&#xff0c;是考虑当前市场软件应用有一大部分是需要把业务数据做出大屏&#xff0c;很多政府项目对大屏需求特别高&#xff0c;还有生产企业项目也对大屏有需求&#xff0c;没有提供基础规范的后台框架&#xff0c;在开发大屏需要很多时间去基…

Mentor Xpedition怎么切换中英文界面

1、Mentor Xpedition的Layout界面&#xff0c;切换中英文的方法如下图&#xff1b; 切换英文设置&#xff0c;设置系统环境变量&#xff1a;MGC_PCB_LANGUAGEEnglish&#xff0c;重新打开软件即可切换成中文界面&#xff1b; 如果想要在切换成中文&#xff0c;把标量值改为Chi…

万能引用与完美转发

万能引用与完美转发 万能引用完美转发完美转发的应用场景万能引用的一个小点 万能引用 注意&#xff1a;当&&出现在模板中时&#xff0c;不是右值引用&#xff0c;而是叫万能引用。比如下面的T&& t template<typename T> void PerfectForward(T&&a…

民宿在线预订系统

摘要 随着国家的发展&#xff0c;人们也更加重视自己的业余时间。在特定的假期或休闲时间外出度假已逐渐成为这个时代的趋势。在我国&#xff0c;随着经济的发展和城市居民物质生活水平的提高&#xff0c;旅游业也呈现出越来越受欢迎的趋势。同时随着人口的快速流动&#xff0…

代理网络基础设施 101:增强安全性、速度和可扩展性

编辑代理网络在现代网络架构中发挥着重要作用&#xff0c;充当管理和重新路由数据流的中介。它们处理的数据可以是各种类型&#xff0c;包括搜索查询和潜在的敏感客户信息&#xff0c;这凸显了它们在数据安全方面的作用。 然而&#xff0c;代理的好处不仅限于安全性。它们为用…

人工智能与生物信息组学 || 2. 非编码 RNA 与疾病关联分析 || 2.2 非编码 miRNA 与疾病关联关系预测

非编码 miRNA 与疾病关联关系预测 越来越多的研究表明&#xff0c;一个复杂疾病通常经由多个 miRNA 协同调控&#xff0c;一个 miRNA 通常参与多个疾病的发生发展过程。因此&#xff0c;预测 miRNA 与疾病的关联关系成为一个当前的研究热点。下面我们将探讨一种 miRNA 和疾病关…

技术驱动会展:展位导航系统的架构与实现

随着会展行业的快速发展&#xff0c;大型会展中心面临着如何提升参展者体验、提高招商效率的挑战。针对客户反馈的展馆面积大、展位查找困难等问题&#xff0c;维小帮提出一套智慧会展导航解决方案&#xff0c;旨在通过先进的室内导航技术提升会展中心的运营效率和参展者的满意…

小阿轩yx-MySQL数据库初体验

小阿轩yx-MySQL数据库初体验 数据库简介 21 世纪迈入了“信息爆炸时代”&#xff0c;大量的数据、信息在不断产生&#xff0c;伴随而来的就是如何安全、有效地存储、检索和管理它们。 对数据的有效存储、高效访问、方便共享和安全控制已经成为信息时代亟待解决的问题。 使用…

QThread 与QObject::moveToThread在UI中的应用

1. QThread的两种用法 第一种用法就是继承QThread&#xff0c;然后覆写 virtual void run()&#xff0c; 这种用法的缺点是不能利用信号槽机制。 第二种用法就是创建一个线程&#xff0c;创建一个对象&#xff0c;再将对象moveToThread, 这种可以充分利用信号槽机制&#xff…

canal 服务安装

简介&#xff1a;Canal 是阿里巴巴开源的一个基于 MySQL 数据库增量日志解析的中间件&#xff0c;用于提供准实时的数据同步功能。 准备工作 1.修改配置文件 ,需要先开启 Binlog 写入功能&#xff0c;配置 binlog-format 为 ROW 模式&#xff0c;my.cnf 中配置如下&#xf…