// JSPL的计算过程总结: // // 输入: 传入的会话ID或相关数据 // 哈希处理: 使用DJB2算法变种对输入进行哈希 // 种子生成: 结合时间戳和常量生成加密种子 // 数据收集: 收集各种浏览器指纹和环境信息 // 加密处理: 使用自定义的流加密算法对数据进行加密 // Base64编码: 最终使用自定义字符集进行Base64编码 // 这个函数生成的第三个返回值就是用于JSPL参数的加密字符串 var zn = (function () { // 检查是否已经初始化 // if (Pn) { // return Nn; // } Pn = true; var n = "unknown"; // 默认返回值 var constantSeed = 11027890091; // 常量种子 var o = true; // 状态标志 // 字符串哈希函数 - DJB2算法的变种 function djb2HashString(str) { if (!str) { return n; } var hash = 0; for (var i = 0; i < str.length; i++) { hash = (hash << 8) - hash + str.charCodeAt(i) | 0; } return hash === 0 ? n : hash; } // 映射函数 - 用于Base64编码的自定义字符集 function mapChar(n) { if (n > 37) { return 59 + n; } else if (n > 11) { return 53 + n; } else if (n > 1) { return 46 + n; } else { return n * 50 + 45; } } // 线性同余生成器 - 用于生成伪随机数 function lcg(n) { return (n = (n ^= n << 13) ^ n >> 17) ^ n << 5; } // 加密随机数生成器 function createRandomGenerator(seed, initialValue) { var state = seed; var counter = -1; var value = initialValue; var firstCall = o; o = false; var buffer = null; return function (peek) { var result; if (buffer !== null) { result = buffer; buffer = null; } else { if (++counter > 2) { state = lcg(state); counter = 0; } result = ((result = state >> 16 - counter * 8) ^ (firstCall ? --value : 0)) & 255; if (peek) { buffer = result; } } return result; }; } // 主加密函数 return Nn = function (inputString, additionalData) { // console.log("inputString:" + inputString) // console.log("additionalData:" + additionalData) // 混合输入数据生成种子 var seed = constantSeed ^ djb2HashString(inputString) ^ additionalData; // 生成基于时间的随机数 var timeBasedRandom = lcg(lcg(Date.now() >> 3 ^ constantSeed) * constantSeed); // 创建随机数生成器 var randomGenerator = createRandomGenerator(seed, timeBasedRandom); // 存储加密数据的数组 var encryptedData = []; var isFirstCall = true; var callCounter = 0; // UTF-8编码和加密函数 function utf8EncodeAndEncrypt(str) { var bytes = []; var byteIndex = 0; // UTF-8编码 for (var i = 0; i < str.length; i++) { var charCode = str.charCodeAt(i); if (charCode < 128) { bytes[byteIndex++] = charCode; } else { if (charCode < 2048) { bytes[byteIndex++] = charCode >> 6 | 192; } else { if ((charCode & 64512) == 55296 && i + 1 < str.length && (str.charCodeAt(i + 1) & 64512) == 56320) { charCode = 65536 + ((charCode & 1023) << 10) + (str.charCodeAt(++i) & 1023); bytes[byteIndex++] = charCode >> 18 | 240; bytes[byteIndex++] = charCode >> 12 & 63 | 128; } else { bytes[byteIndex++] = charCode >> 12 | 224; } bytes[byteIndex++] = charCode >> 6 & 63 | 128; } bytes[byteIndex++] = charCode & 63 | 128; } } // XOR加密 for (var j = 0; j < bytes.length; j++) { bytes[j] ^= randomGenerator(); } return bytes; } // JSON序列化函数 function safeJsonStringify(obj) { try { return JSON.stringify(obj); } catch (e) { } } // 数据收集和加密函数 function collectAndEncrypt(key, value) { // console.log("key:" + key) // console.log("value:" + value) if (!(typeof key != "string" || key.length == 0 || value && ["number", "string", "boolean"].indexOf(typeof value) == -1)) { let serializedKey = safeJsonStringify(key); // console.log("serializedKey:" + serializedKey) value = safeJsonStringify(value); // console.log("serializedValue:" + value) if (key && value !== undefined && key !== "xt1") { // 添加分隔符和加密数据 encryptedData.push(randomGenerator() ^ (encryptedData.length ? 44 : 123)); Array.prototype.push.apply(encryptedData, utf8EncodeAndEncrypt(serializedKey)); encryptedData.push(randomGenerator() ^ 58); Array.prototype.push.apply(encryptedData, utf8EncodeAndEncrypt(value)); // 第一次调用时添加额外数据 if (isFirstCall) { isFirstCall = false; // var hsv = typeof window._hsv == "string" && window._hsv.length > 0 || // typeof window._hsv == "number" && !isNaN(window._hsv) ? window._hsv : 33; //todo hsv 怎么拿到 var hsv = 33; collectAndEncrypt("r3n", hsv); } } } } var processedKeys = new Set(); // 返回三个函数的数组 return [ // 1. 主要的数据收集函数 collectAndEncrypt, // 2. 带去重保护的数据收集函数 function (key, value) { if (!processedKeys.has(key)) { processedKeys.add(key); collectAndEncrypt(key, value); } }, // 3. 最终生成加密字符串的函数 function (finalKey) { var finalRandomGen = createRandomGenerator(djb2HashString(finalKey) ^ 1809053797, timeBasedRandom); collectAndEncrypt("bpc", ++callCounter); // 对收集的数据进行最终加密 var finalEncrypted = []; for (var i = 0; i < encryptedData.length; i++) { finalEncrypted.push(encryptedData[i] ^ finalRandomGen()); } // 添加结束标记 finalEncrypted.push(randomGenerator(true) ^ 125 ^ finalRandomGen()); // Base64编码 var resultBytes = finalEncrypted; var resultChars = []; var baseValue = timeBasedRandom; for (var pos = 0; pos < resultBytes.length;) { var triplet = (--baseValue & 255 ^ resultBytes[pos++]) << 16 | (--baseValue & 255 ^ resultBytes[pos++]) << 8 | --baseValue & 255 ^ resultBytes[pos++]; resultChars.push(String.fromCharCode(mapChar(triplet >> 18 & 63))); resultChars.push(String.fromCharCode(mapChar(triplet >> 12 & 63))); resultChars.push(String.fromCharCode(mapChar(triplet >> 6 & 63))); resultChars.push(String.fromCharCode(mapChar(triplet & 63))); } // 处理剩余字节 if (resultBytes.length % 3) { resultChars.length -= 3 - (resultBytes.length % 3); } return resultChars.join(""); } ]; }; })(); // 创建一个工具函数来生成JSPL function createJSPLGenerator(dateTimeStamp) { return { generate: function (sessionData, fingerprintData) { // let dateTimeStamp = Math.floor(Date.now() / 1000) // console.log("dateTimeStamp : " + dateTimeStamp) // 使用会话数据作为输入 var functions = zn(sessionData, dateTimeStamp); var collect = functions[1]; // 收集函数 var generate = functions[2]; //加密函数 // 收集指纹数据 for (var key in fingerprintData) { if (fingerprintData.hasOwnProperty(key)) { collect(key, fingerprintData[key]); } } // 生成并返回JSPL return generate("jspl"); } }; } // print process.argv // process.argv.forEach(function (val, index, array) { // console.log(index + ': ' + val); // }); var fingerprint = undefined var dateTimeStamp = undefined if (process.argv[2] != undefined) { fingerprint = JSON.parse(process.argv[2]) } dateTimeStamp = JSON.parse(process.argv[3]) // main // if (dateTimeStamp == undefined) { // dateTimeStamp = Math.floor(Date.now() / 1000) // } // let dateTimeStamp = Math.floor(Date.now() / 1000) // let dateTimeStamp = 1754908260 // console.log(dateTimeStamp) // 使用示例 let jsplGenerator = createJSPLGenerator(dateTimeStamp); // fingerprint = { // "nddc": 1, // "r3n": 33, // "exp8": 0, // "uid": null, // "bci": true, // "bcl": 0.8, // "bct": "Infinity", // "bdt": "Infinity", // "dp0": false, // "ucdv": false, // "wdifrm": false, // "iwgl": "undefined", // "npmtm": false, // "wdif": false, // "wdifpnh": 2800984568, // "lg": "fr-FR", // "isb": false, // "idp": true, // "crt": 0, // "vnd": "Google Inc.", // "bid": "NA", // "med": "defined", // "pltod": false, // "csssp": "", // "awe": false, // "phe": false, // "dat": false, // "nm": false, // "geb": false, // "sqt": false, // "pf": "Linux armv81", // "hc": 8, // "br_oh": 745, // "br_ow": 393, // "ua": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36", // "wbd": false, // "ts_mtp": 5, // "mob": true, // "lgs": ["fr-FR", "en-US", "zh-CN", "zh", "fr", "en"], // "dvm": 4, // "hcovdr": false, // "plovdr": false, // "ftsovdr": false, // "orf": "debug", // "ttst": 0.8517814137469564, // "br_w": 393, // "br_h": 745, // "br_iw": 513, // "br_ih": 847, // "ars_w": 393, // "ars_h": 876, // "rs_w": 393, // "rs_h": 876, // "rs_cd": 24, // "pr": 2.75, // "so": "portrait-primary", // "vco": "", // "vcots": false, // "vch": "probably", // "vchts": true, // "vcw": "probably", // "vcwts": true, // "vc3": "maybe", // "vc3ts": false, // "vcmp": "", // "vcmpts": false, // "vcq": "", // "vcqts": false, // "vc1": "probably", // "vc1ts": true, // "cssS": "3.93,0.39,12.24,9.75,5.64,10.98,13.46,2.19,6.51", // "css0": "7,75,0", // "css1": "9.74354,0.354646,-0.00922698,0.000685511,0.203723,-5.61673,-0.755238,0.0561098,-0.0279023,0.481607,-10.9534,0.813777,-0.375565,6.48243,-147.433,11.9534", // "cssH": "15px", // "plu": "", // "plgod": false, // "plg": 0, // "plgne": "NA", // "plgre": "NA", // "plgof": "NA", // "plggt": "NA", // "mmt": "empty", // "bchk": "3223aeb6721e0d0917e792818d193ac88dcd62fad5cad7bf7a2b2b473ecf58ee60f018dbdb1a5832e8dc6528387b0745971dbcd82387261e9a4e3f", // "nt_tcp": 0, // "nt_dns": 0, // "nt_rd": 0, // "nt_irt": -29.600000008940697, // "nt_rt": 1129, // "nt_tls": 6.700000002980232, // "nt_ttf": 1166.7000000029802, // "nt_swt": 22.900000005960464, // "nt_csd": 411060, // "nt_nhp": "h2", // "nt_rdc": 0, // "nt_it": "navigation", // "nt_prs": 6.700000002980232, // "nt_esc": 0, // "nt_ttrd": null, // "nt_le": 3.0999999940395355, // "nt_dcle": 141.79999999701977, // "nt_di": 1415.2000000029802, // "nt_dc": 2862.6000000089407, // "ccsT": "Error\nat S (https://d.digital.hermes/tags.js:173:22)\nat Un.C (https://d.digital.hermes/tags.js:1252:41\nat nrWrapper (https://www.hermes.com/fr/fr/category/femme/Sacs%20et%20pochettes%20pour%20Femme%20_%20Herme%CC%80s%20France.html:7:13468)", // "ccsB": "tags.js:1252:41 at nrWrapper (sac-p-tit-arcon-H085871CKAO.html:7:13468)", // "ccsH": "1050544242", // "ccsV": ",993b46baf0942a343b7e6b02fa3f8eef64727f077d3b0055af56e6994dcaf046", // "muev": false, // "pro_t": true, // "wglo": true, // "prso": true, // "wbst": true, // "psn": true, // "edp": true, // "addt": true, // "wsdc": true, // "ccsr": true, // "nuad": true, // "bcda": true, // "idn": true, // "capi": true, // "svde": true, // "vpbq": true, // "mq": "aptr:coarse,ahvr:none", // "aco": "probably", // "acots": false, // "acmp": "probably", // "acmpts": true, // "acw": "probably", // "acwts": false, // "acma": "maybe", // "acmats": false, // "acaa": "probably", // "acaats": true, // "ac3": "", // "ac3ts": false, // "acf": "probably", // "acfts": false, // "acmp4": "maybe", // "acmp4ts": false, // "acmp3": "probably", // "acmp3ts": false, // "acwm": "maybe", // "acwmts": false, // "ocpt": false, // "ckwa": false, // "spwn": false, // "emt": false, // "bfr": false, // "tz": -120, // "hdn": false, // "xt1": false, // "cdhf": false, // "eva": 33, // "cokys": ",loadTimes,csi,app", // "ecpc": false, // "nhi": ",64,true,Nexus 5,Android,6.0,138.0.7204.184,false", // "k_lyts": 48, // "k_lytk": "kg20va`l\u00a7'w8mh.71pdfoqcn[zy365x/\\,-4bt9siu=j;r]e", // "emd": "k:ai,vi,ao", // "wwl": false, // "glvd": "Google Inc. (ARM)", // "glrd": "ANGLE (ARM,Mali-G57 MC2,OpenGL ES 3.2)", // "tzp": "Europe/Paris", // "isf": true, // "isf2": false, // "dt": false, // "fph": 416468867, // "jset": 1754750959 // } // console.log("received fringerprint is :"+fingerprint) // console.log(fingerprint) let jspl = jsplGenerator.generate("user_session_12345", fingerprint); console.log(jspl);