DouyinWebSign

DouyinWebSign Utils

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/513451/1468972/DouyinWebSign.js

  1. // ==UserScript==
  2. // @name DouyinWebSign
  3. // @namespace douyin-web-sign
  4. // @version 1.0.0
  5. // @description DouyinWebSign Utils
  6. // @author Dong <dong@freshoo.cn>
  7. // @match https://*.douyin.com/*
  8. // @include *
  9. // @license MIT
  10. // ==/UserScript==
  11.  
  12. var DouyinWebSign = (function (exports) {
  13. // All the content in this article is only for learning and communication use, not for any other purpose, strictly prohibited for commercial use and illegal use, otherwise all the consequences are irrelevant to the author!
  14. function rc4_encrypt(plaintext, key) {
  15. var s = [];
  16. for (var i = 0; i < 256; i++) {
  17. s[i] = i;
  18. }
  19. var j = 0;
  20. for (var i = 0; i < 256; i++) {
  21. j = (j + s[i] + key.charCodeAt(i % key.length)) % 256;
  22. var temp = s[i];
  23. s[i] = s[j];
  24. s[j] = temp;
  25. }
  26.  
  27. var i = 0;
  28. var j = 0;
  29. var cipher = [];
  30. for (var k = 0; k < plaintext.length; k++) {
  31. i = (i + 1) % 256;
  32. j = (j + s[i]) % 256;
  33. var temp = s[i];
  34. s[i] = s[j];
  35. s[j] = temp;
  36. var t = (s[i] + s[j]) % 256;
  37. cipher.push(String.fromCharCode(s[t] ^ plaintext.charCodeAt(k)));
  38. }
  39. return cipher.join('');
  40. }
  41.  
  42. function le(e, r) {
  43. return (e << (r %= 32) | e >>> 32 - r) >>> 0
  44. }
  45.  
  46. function de(e) {
  47. return 0 <= e && e < 16 ? 2043430169 : 16 <= e && e < 64 ? 2055708042 : void console['error']("invalid j for constant Tj")
  48. }
  49.  
  50. function pe(e, r, t, n) {
  51. return 0 <= e && e < 16 ? (r ^ t ^ n) >>> 0 : 16 <= e && e < 64 ? (r & t | r & n | t & n) >>> 0 : (console['error']('invalid j for bool function FF'),
  52. 0)
  53. }
  54.  
  55. function he(e, r, t, n) {
  56. return 0 <= e && e < 16 ? (r ^ t ^ n) >>> 0 : 16 <= e && e < 64 ? (r & t | ~r & n) >>> 0 : (console['error']('invalid j for bool function GG'),
  57. 0)
  58. }
  59.  
  60. function reset() {
  61. this.reg[0] = 1937774191,
  62. this.reg[1] = 1226093241,
  63. this.reg[2] = 388252375,
  64. this.reg[3] = 3666478592,
  65. this.reg[4] = 2842636476,
  66. this.reg[5] = 372324522,
  67. this.reg[6] = 3817729613,
  68. this.reg[7] = 2969243214,
  69. this["chunk"] = [],
  70. this["size"] = 0
  71. }
  72.  
  73. function write(e) {
  74. var a = "string" == typeof e ? function (e) {
  75. n = encodeURIComponent(e)['replace'](/%([0-9A-F]{2})/g, (function (e, r) {
  76. return String['fromCharCode']("0x" + r)
  77. }
  78. ))
  79. , a = new Array(n['length']);
  80. return Array['prototype']['forEach']['call'](n, (function (e, r) {
  81. a[r] = e.charCodeAt(0)
  82. }
  83. )),
  84. a
  85. }(e) : e;
  86. this.size += a.length;
  87. var f = 64 - this['chunk']['length'];
  88. if (a['length'] < f)
  89. this['chunk'] = this['chunk'].concat(a);
  90. else
  91. for (this['chunk'] = this['chunk'].concat(a.slice(0, f)); this['chunk'].length >= 64;)
  92. this['_compress'](this['chunk']),
  93. f < a['length'] ? this['chunk'] = a['slice'](f, Math['min'](f + 64, a['length'])) : this['chunk'] = [],
  94. f += 64
  95. }
  96.  
  97. function sum(e, t) {
  98. e && (this['reset'](),
  99. this['write'](e)),
  100. this['_fill']();
  101. for (var f = 0; f < this.chunk['length']; f += 64)
  102. this._compress(this['chunk']['slice'](f, f + 64));
  103. var i = null;
  104. if (t == 'hex') {
  105. i = "";
  106. for (f = 0; f < 8; f++)
  107. i += se(this['reg'][f]['toString'](16), 8, "0")
  108. } else
  109. for (i = new Array(32),
  110. f = 0; f < 8; f++) {
  111. var c = this.reg[f];
  112. i[4 * f + 3] = (255 & c) >>> 0,
  113. c >>>= 8,
  114. i[4 * f + 2] = (255 & c) >>> 0,
  115. c >>>= 8,
  116. i[4 * f + 1] = (255 & c) >>> 0,
  117. c >>>= 8,
  118. i[4 * f] = (255 & c) >>> 0
  119. }
  120. return this['reset'](),
  121. i
  122. }
  123.  
  124. function _compress(t) {
  125. if (t < 64)
  126. console.error("compress error: not enough data");
  127. else {
  128. for (var f = function (e) {
  129. for (var r = new Array(132), t = 0; t < 16; t++)
  130. r[t] = e[4 * t] << 24,
  131. r[t] |= e[4 * t + 1] << 16,
  132. r[t] |= e[4 * t + 2] << 8,
  133. r[t] |= e[4 * t + 3],
  134. r[t] >>>= 0;
  135. for (var n = 16; n < 68; n++) {
  136. var a = r[n - 16] ^ r[n - 9] ^ le(r[n - 3], 15);
  137. a = a ^ le(a, 15) ^ le(a, 23),
  138. r[n] = (a ^ le(r[n - 13], 7) ^ r[n - 6]) >>> 0
  139. }
  140. for (n = 0; n < 64; n++)
  141. r[n + 68] = (r[n] ^ r[n + 4]) >>> 0;
  142. return r
  143. }(t), i = this['reg'].slice(0), c = 0; c < 64; c++) {
  144. var o = le(i[0], 12) + i[4] + le(de(c), c)
  145. , s = ((o = le(o = (4294967295 & o) >>> 0, 7)) ^ le(i[0], 12)) >>> 0
  146. , u = pe(c, i[0], i[1], i[2]);
  147. u = (4294967295 & (u = u + i[3] + s + f[c + 68])) >>> 0;
  148. var b = he(c, i[4], i[5], i[6]);
  149. b = (4294967295 & (b = b + i[7] + o + f[c])) >>> 0,
  150. i[3] = i[2],
  151. i[2] = le(i[1], 9),
  152. i[1] = i[0],
  153. i[0] = u,
  154. i[7] = i[6],
  155. i[6] = le(i[5], 19),
  156. i[5] = i[4],
  157. i[4] = (b ^ le(b, 9) ^ le(b, 17)) >>> 0
  158. }
  159. for (var l = 0; l < 8; l++)
  160. this['reg'][l] = (this['reg'][l] ^ i[l]) >>> 0
  161. }
  162. }
  163.  
  164. function _fill() {
  165. var a = 8 * this['size']
  166. , f = this['chunk']['push'](128) % 64;
  167. for (64 - f < 8 && (f -= 64); f < 56; f++)
  168. this.chunk['push'](0);
  169. for (var i = 0; i < 4; i++) {
  170. var c = Math['floor'](a / 4294967296);
  171. this['chunk'].push(c >>> 8 * (3 - i) & 255)
  172. }
  173. for (i = 0; i < 4; i++)
  174. this['chunk']['push'](a >>> 8 * (3 - i) & 255)
  175.  
  176. }
  177.  
  178. function SM3() {
  179. this.reg = [];
  180. this.chunk = [];
  181. this.size = 0;
  182. this.reset()
  183. }
  184. SM3.prototype.reset = reset;
  185. SM3.prototype.write = write;
  186. SM3.prototype.sum = sum;
  187. SM3.prototype._compress = _compress;
  188. SM3.prototype._fill = _fill;
  189.  
  190. function result_encrypt(long_str, num = null) {
  191. let s_obj = {
  192. "s0": "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  193. "s1": "Dkdpgh4ZKsQB80/Mfvw36XI1R25+WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
  194. "s2": "Dkdpgh4ZKsQB80/Mfvw36XI1R25-WUAlEi7NLboqYTOPuzmFjJnryx9HVGcaStCe=",
  195. "s3": "ckdp1h4ZKsUB80/Mfvw36XIgR25+WQAlEi7NLboqYTOPuzmFjJnryx9HVGDaStCe",
  196. "s4": "Dkdpgh2ZmsQB80/MfvV36XI1R45-WUAlEixNLwoqYTOPuzKFjJnry79HbGcaStCe"
  197. }
  198. let constant = {
  199. "0": 16515072,
  200. "1": 258048,
  201. "2": 4032,
  202. "str": s_obj[num],
  203. }
  204.  
  205. let result = "";
  206. let lound = 0;
  207. let long_int = get_long_int(lound, long_str);
  208. for (let i = 0; i < long_str.length / 3 * 4; i++) {
  209. if (Math.floor(i / 4) !== lound) {
  210. lound += 1;
  211. long_int = get_long_int(lound, long_str);
  212. }
  213. let key = i % 4;
  214. switch (key) {
  215. case 0:
  216. temp_int = (long_int & constant["0"]) >> 18;
  217. result += constant["str"].charAt(temp_int);
  218. break;
  219. case 1:
  220. temp_int = (long_int & constant["1"]) >> 12;
  221. result += constant["str"].charAt(temp_int);
  222. break;
  223. case 2:
  224. temp_int = (long_int & constant["2"]) >> 6;
  225. result += constant["str"].charAt(temp_int);
  226. break;
  227. case 3:
  228. temp_int = long_int & 63;
  229. result += constant["str"].charAt(temp_int);
  230. break;
  231. default:
  232. break;
  233. }
  234. }
  235. return result;
  236. }
  237.  
  238. function get_long_int(round, long_str) {
  239. round = round * 3;
  240. return (long_str.charCodeAt(round) << 16) | (long_str.charCodeAt(round + 1) << 8) | (long_str.charCodeAt(round + 2));
  241. }
  242.  
  243. function gener_random(random, option) {
  244. return [
  245. (random & 255 & 170) | option[0] & 85, // 163
  246. (random & 255 & 85) | option[0] & 170, //87
  247. (random >> 8 & 255 & 170) | option[1] & 85, //37
  248. (random >> 8 & 255 & 85) | option[1] & 170, //41
  249. ]
  250. }
  251.  
  252. //////////////////////////////////////////////
  253. function generate_rc4_bb_str(url_search_params, user_agent, window_env_str, suffix = "cus", Arguments = [0, 1, 14]) {
  254. let sm3 = new SM3()
  255. let start_time = Date.now()
  256. /**
  257. * 进行3次加密处理
  258. * 1: url_search_params两次sm3之的结果
  259. * 2: 对后缀两次sm3之的结果
  260. * 3: 对ua处理之后的结果
  261. */
  262. // url_search_params两次sm3之的结果
  263. let url_search_params_list = sm3.sum(sm3.sum(url_search_params + suffix))
  264. // 对后缀两次sm3之的结果
  265. let cus = sm3.sum(sm3.sum(suffix))
  266. // 对ua处理之后的结果
  267. let ua = sm3.sum(result_encrypt(rc4_encrypt(user_agent, String.fromCharCode.apply(null, [0.00390625, 1, 14])), "s3"))
  268. //
  269. let end_time = Date.now()
  270. // b
  271. let b = {
  272. 8: 3, // 固定
  273. 10: end_time, //3次加密结束时间
  274. 15: {
  275. "aid": 6383,
  276. "pageId": 6241,
  277. "boe": false,
  278. "ddrt": 7,
  279. "paths": {
  280. "include": [
  281. {},
  282. {},
  283. {},
  284. {},
  285. {},
  286. {},
  287. {}
  288. ],
  289. "exclude": []
  290. },
  291. "track": {
  292. "mode": 0,
  293. "delay": 300,
  294. "paths": []
  295. },
  296. "dump": true,
  297. "rpU": ""
  298. },
  299. 16: start_time, //3次加密开始时间
  300. 18: 44, //固定
  301. 19: [1, 0, 1, 5],
  302. }
  303.  
  304. //3次加密开始时间
  305. b[20] = (b[16] >> 24) & 255
  306. b[21] = (b[16] >> 16) & 255
  307. b[22] = (b[16] >> 8) & 255
  308. b[23] = b[16] & 255
  309. b[24] = (b[16] / 256 / 256 / 256 / 256) >> 0
  310. b[25] = (b[16] / 256 / 256 / 256 / 256 / 256) >> 0
  311.  
  312. // 参数Arguments [0, 1, 14, ...]
  313. // let Arguments = [0, 1, 14]
  314. b[26] = (Arguments[0] >> 24) & 255
  315. b[27] = (Arguments[0] >> 16) & 255
  316. b[28] = (Arguments[0] >> 8) & 255
  317. b[29] = Arguments[0] & 255
  318.  
  319. b[30] = (Arguments[1] / 256) & 255
  320. b[31] = (Arguments[1] % 256) & 255
  321. b[32] = (Arguments[1] >> 24) & 255
  322. b[33] = (Arguments[1] >> 16) & 255
  323.  
  324. b[34] = (Arguments[2] >> 24) & 255
  325. b[35] = (Arguments[2] >> 16) & 255
  326. b[36] = (Arguments[2] >> 8) & 255
  327. b[37] = Arguments[2] & 255
  328.  
  329. // (url_search_params + "cus") 两次sm3之的结果
  330. /**let url_search_params_list = [
  331. 91, 186, 35, 86, 143, 253, 6, 76,
  332. 34, 21, 167, 148, 7, 42, 192, 219,
  333. 188, 20, 182, 85, 213, 74, 213, 147,
  334. 37, 155, 93, 139, 85, 118, 228, 213
  335. ]*/
  336. b[38] = url_search_params_list[21]
  337. b[39] = url_search_params_list[22]
  338.  
  339. // ("cus") 对后缀两次sm3之的结果
  340. /**
  341. * let cus = [
  342. 136, 101, 114, 147, 58, 77, 207, 201,
  343. 215, 162, 154, 93, 248, 13, 142, 160,
  344. 105, 73, 215, 241, 83, 58, 51, 43,
  345. 255, 38, 168, 141, 216, 194, 35, 236
  346. ]*/
  347. b[40] = cus[21]
  348. b[41] = cus[22]
  349.  
  350. // 对ua处理之后的结果
  351. /**
  352. * let ua = [
  353. 129, 190, 70, 186, 86, 196, 199, 53,
  354. 99, 38, 29, 209, 243, 17, 157, 69,
  355. 147, 104, 53, 23, 114, 126, 66, 228,
  356. 135, 30, 168, 185, 109, 156, 251, 88
  357. ]*/
  358. b[42] = ua[23]
  359. b[43] = ua[24]
  360.  
  361. //3次加密结束时间
  362. b[44] = (b[10] >> 24) & 255
  363. b[45] = (b[10] >> 16) & 255
  364. b[46] = (b[10] >> 8) & 255
  365. b[47] = b[10] & 255
  366. b[48] = b[8]
  367. b[49] = (b[10] / 256 / 256 / 256 / 256) >> 0
  368. b[50] = (b[10] / 256 / 256 / 256 / 256 / 256) >> 0
  369.  
  370.  
  371. // object配置项
  372. b[51] = b[15]['pageId']
  373. b[52] = (b[15]['pageId'] >> 24) & 255
  374. b[53] = (b[15]['pageId'] >> 16) & 255
  375. b[54] = (b[15]['pageId'] >> 8) & 255
  376. b[55] = b[15]['pageId'] & 255
  377.  
  378. b[56] = b[15]['aid']
  379. b[57] = b[15]['aid'] & 255
  380. b[58] = (b[15]['aid'] >> 8) & 255
  381. b[59] = (b[15]['aid'] >> 16) & 255
  382. b[60] = (b[15]['aid'] >> 24) & 255
  383.  
  384. // 中间进行了环境检测
  385. // 代码索引: 2496 索引值: 17 (索引64关键条件)
  386. // '1536|747|1536|834|0|30|0|0|1536|834|1536|864|1525|747|24|24|Win32'.charCodeAt()得到65位数组
  387. /**
  388. * let window_env_list = [49, 53, 51, 54, 124, 55, 52, 55, 124, 49, 53, 51, 54, 124, 56, 51, 52, 124, 48, 124, 51,
  389. * 48, 124, 48, 124, 48, 124, 49, 53, 51, 54, 124, 56, 51, 52, 124, 49, 53, 51, 54, 124, 56,
  390. * 54, 52, 124, 49, 53, 50, 53, 124, 55, 52, 55, 124, 50, 52, 124, 50, 52, 124, 87, 105, 110,
  391. * 51, 50]
  392. */
  393. let window_env_list = [];
  394. for (let index = 0; index < window_env_str.length; index++) {
  395. window_env_list.push(window_env_str.charCodeAt(index))
  396. }
  397. b[64] = window_env_list.length
  398. b[65] = b[64] & 255
  399. b[66] = (b[64] >> 8) & 255
  400.  
  401. b[69] = [].length
  402. b[70] = b[69] & 255
  403. b[71] = (b[69] >> 8) & 255
  404.  
  405. b[72] = b[18] ^ b[20] ^ b[26] ^ b[30] ^ b[38] ^ b[40] ^ b[42] ^ b[21] ^ b[27] ^ b[31] ^ b[35] ^ b[39] ^ b[41] ^ b[43] ^ b[22] ^
  406. b[28] ^ b[32] ^ b[36] ^ b[23] ^ b[29] ^ b[33] ^ b[37] ^ b[44] ^ b[45] ^ b[46] ^ b[47] ^ b[48] ^ b[49] ^ b[50] ^ b[24] ^
  407. b[25] ^ b[52] ^ b[53] ^ b[54] ^ b[55] ^ b[57] ^ b[58] ^ b[59] ^ b[60] ^ b[65] ^ b[66] ^ b[70] ^ b[71]
  408. let bb = [
  409. b[18], b[20], b[52], b[26], b[30], b[34], b[58], b[38], b[40], b[53], b[42], b[21], b[27], b[54], b[55], b[31],
  410. b[35], b[57], b[39], b[41], b[43], b[22], b[28], b[32], b[60], b[36], b[23], b[29], b[33], b[37], b[44], b[45],
  411. b[59], b[46], b[47], b[48], b[49], b[50], b[24], b[25], b[65], b[66], b[70], b[71]
  412. ]
  413. bb = bb.concat(window_env_list).concat(b[72])
  414. return rc4_encrypt(String.fromCharCode.apply(null, bb), String.fromCharCode.apply(null, [121]));
  415. }
  416.  
  417. function generate_random_str() {
  418. let random_str_list = []
  419. random_str_list = random_str_list.concat(gener_random(Math.random() * 10000, [3, 45]))
  420. random_str_list = random_str_list.concat(gener_random(Math.random() * 10000, [1, 0]))
  421. random_str_list = random_str_list.concat(gener_random(Math.random() * 10000, [1, 5]))
  422. return String.fromCharCode.apply(null, random_str_list)
  423. }
  424.  
  425. function generate_a_bogus(url_search_params, user_agent) {
  426. /**
  427. * url_search_params:"device_platform=webapp&aid=6383&channel=channel_pc_web&update_version_code=170400&pc_client_type=1&version_code=170400&version_name=17.4.0&cookie_enabled=true&screen_width=1536&screen_height=864&browser_language=zh-CN&browser_platform=Win32&browser_name=Chrome&browser_version=123.0.0.0&browser_online=true&engine_name=Blink&engine_version=123.0.0.0&os_name=Windows&os_version=10&cpu_core_num=16&device_memory=8&platform=PC&downlink=10&effective_type=4g&round_trip_time=50&webid=7362810250930783783&msToken=VkDUvz1y24CppXSl80iFPr6ez-3FiizcwD7fI1OqBt6IICq9RWG7nCvxKb8IVi55mFd-wnqoNkXGnxHrikQb4PuKob5Q-YhDp5Um215JzlBszkUyiEvR"
  428. * user_agent:"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
  429. */
  430. let result_str = generate_random_str() + generate_rc4_bb_str(
  431. url_search_params,
  432. user_agent,
  433. "1536|747|1536|834|0|30|0|0|1536|834|1536|864|1525|747|24|24|Win32"
  434. );
  435. return result_encrypt(result_str, "s4") + "=";
  436. }
  437.  
  438. function getABogus(url, user_agent) {
  439. if (url.includes('https://')) {
  440. url = new URLSearchParams(new URL(url).search).toString()
  441. }
  442. !user_agent ? user_agent = navigator.userAgent : user_agent
  443. return generate_a_bogus(url, user_agent)
  444. }
  445.  
  446. function getVerifyFp() {
  447. var e = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("")
  448. , t = e.length
  449. , r = new Date().getTime().toString(36)
  450. , n = [];
  451. n[8] = n[13] = n[18] = n[23] = "_",
  452. n[14] = "4";
  453. for (var o = 0, i = void 0; o < 36; o++)
  454. n[o] || (i = 0 | Math.random() * t,
  455. n[o] = e[19 == o ? 3 & i | 8 : i]);
  456. return "verify_" + r + "_" + n.join("")
  457. }
  458.  
  459. function getRandomString(len) {
  460. let _charStr = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789',
  461. min = 0,
  462. max = _charStr.length - 1,
  463. _str = ''; //定义随机字符串 变量
  464. //判断是否指定长度,否则默认长度为15
  465. len = len || 15;
  466. //循环生成字符串
  467. for (var i = 0, index; i < len; i++) {
  468. index = (function (randomIndexFunc, i) {
  469. return randomIndexFunc(min, max, i, randomIndexFunc);
  470. })(function (min, max, i, _self) {
  471. let indexTemp = Math.floor(Math.random() * (max - min + 1) + min),
  472. numStart = _charStr.length - 10;
  473. if (i == 0 && indexTemp >= numStart) {
  474. indexTemp = _self(min, max, i, _self);
  475. }
  476. return indexTemp;
  477. }, i);
  478. _str += _charStr[index];
  479. }
  480. return _str;
  481. }
  482.  
  483. exports.getABogus = getABogus;
  484. exports.getVerifyFp = getVerifyFp;
  485. exports.getRandomString = getRandomString;
  486. return exports;
  487. })({});

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址