ksjsb/tools/jose_decrypt.js
2026-07-30 20:25:56 +08:00

64 lines
2.7 KiB
JavaScript

// Jose $decrypt: verifyParam(base64) -> 明文 JSON。
// 复用 jose_encrypt.js 的单 realm 沙箱; realm.global 暴露 $encrypt/$encode/$decrypt。
// CLI: node tools/jose_decrypt.js '<verifyParam-base64>' -> stdout: 明文 JSON
const fs = require("fs"), vm = require("vm"), path = require("path");
const ENC_PATH = path.join(__dirname, "..", "out", "captcha_net",
"js_07_rm_static_captcha_js_encrypt_ee7d2a41_js.js");
const KEY = "c7b645db-65e8-401f-b38c-4c07c5fff247";
function makeBox() {
const sandbox = {
console: { log: () => {}, error: () => {}, warn: () => {} },
setTimeout, clearTimeout, setImmediate, queueMicrotask, Buffer,
btoa: (s) => Buffer.from(s, "binary").toString("base64"),
atob: (s) => Buffer.from(s, "base64").toString("binary"),
};
vm.createContext(sandbox);
sandbox.window = sandbox; sandbox.self = sandbox; sandbox.global = sandbox;
vm.runInContext(fs.readFileSync(ENC_PATH, "utf-8"), sandbox, { filename: "encrypt.js", timeout: 30000 });
const factory = sandbox.webpackJsonp[0][1]["088e"];
const rq = (id) => id === "b639" ? { Buffer } : id === "dd40" ? (x) => x : {};
const mod = { exports: {} };
factory(mod, mod.exports, rq);
if (!sandbox.Jose) throw new Error("Jose 未加载");
return sandbox;
}
function decrypt(sandbox, verifyParamB64) {
// base64 -> bytes (单 realm: 用沙箱 atob + charCodeAt)
sandbox.__done = null; sandbox.__out = null;
vm.runInContext(`
globalThis.__dec = function(vp){
var s = globalThis.atob(vp);
var u8 = new Uint8Array(Array.prototype.map.call(s, function(c){return c.charCodeAt(0);}));
globalThis.__out=null; globalThis.__done=null;
Jose.call("$decrypt", [u8, ${JSON.stringify(KEY)}, {
suc: function(v){ var o=""; for(var i=0;i<v.length;i++) o+=String.fromCharCode(v[i]); globalThis.__out=o; globalThis.__done="ok"; },
err: function(e){ globalThis.__out="ERR:"+(e&&e.message||e); globalThis.__done="err"; }
}]);
};
`, sandbox);
vm.runInContext(`__dec(${JSON.stringify(verifyParamB64)});`, sandbox);
return new Promise((resolve) => {
const t0 = Date.now();
const iv = setInterval(() => {
if (sandbox.__done !== null || Date.now() - t0 > 5000) {
clearInterval(iv);
resolve(sandbox.__done === "ok" ? sandbox.__out : (sandbox.__out || "ERR:timeout"));
}
}, 5);
});
}
module.exports = { makeBox, decrypt, KEY };
if (require.main === module) {
const arg = process.argv[2];
if (!arg) { console.error("usage: node jose_decrypt.js '<verifyParam-base64>'"); process.exit(2); }
const box = makeBox();
decrypt(box, arg).then((out) => {
if (out && out.indexOf("ERR:") === 0) { console.error(out); process.exit(1); }
process.stdout.write(out || "");
});
}