445 lines
14 KiB
JavaScript
445 lines
14 KiB
JavaScript
// 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); |