Files
WeChatDataAnalysis/tools/weflow_wasm_keystream.js
2977094657 6e127b2e32 feat(sns): 增强朋友圈时间线/媒体获取与实时同步
- 新增 /api/sns/users:按发圈数统计联系人(支持 keyword/limit)
- 新增 /api/sns/realtime/sync_latest:WCDB 实时增量同步到解密库(append-only),并持久化 sync state
- 朋友圈媒体优先走“远程下载+解密”:图片支持 wcdb_decrypt_sns_image,视频/实况支持 ISAAC64(WeFlow 逻辑)
- 增加 WeFlow WASM keystream(Node) 优先 + Python ISAAC64 fallback,提升兼容性
- wcdb_api.dll 支持多路径自动发现/环境变量覆盖,并在状态信息中回传实际使用路径
2026-02-17 23:40:10 +08:00

123 lines
3.0 KiB
JavaScript

// Generate WeChat/WeFlow WxIsaac64 keystream via WeFlow's WASM module.
//
// Usage:
// node tools/weflow_wasm_keystream.js <key> <size>
//
// Prints a base64-encoded keystream to stdout (no extra logs).
const fs = require('fs')
const path = require('path')
const vm = require('vm')
function usageAndExit() {
process.stderr.write('Usage: node tools/weflow_wasm_keystream.js <key> <size>\\n')
process.exit(2)
}
const key = String(process.argv[2] || '').trim()
const size = Number(process.argv[3] || 0)
if (!key || !Number.isFinite(size) || size <= 0) usageAndExit()
const basePath = path.join(__dirname, '..', 'WeFlow', 'electron', 'assets', 'wasm')
const wasmPath = path.join(basePath, 'wasm_video_decode.wasm')
const jsPath = path.join(basePath, 'wasm_video_decode.js')
if (!fs.existsSync(wasmPath) || !fs.existsSync(jsPath)) {
process.stderr.write(`WeFlow WASM assets not found: ${basePath}\\n`)
process.exit(1)
}
const wasmBinary = fs.readFileSync(wasmPath)
const jsContent = fs.readFileSync(jsPath, 'utf8')
let capturedKeystream = null
let resolveInit
let rejectInit
const initPromise = new Promise((res, rej) => {
resolveInit = res
rejectInit = rej
})
const mockGlobal = {
console: { log: () => {}, error: () => {} }, // keep stdout clean
Buffer,
Uint8Array,
Int8Array,
Uint16Array,
Int16Array,
Uint32Array,
Int32Array,
Float32Array,
Float64Array,
BigInt64Array,
BigUint64Array,
Array,
Object,
Function,
String,
Number,
Boolean,
Error,
Promise,
require,
process,
setTimeout,
clearTimeout,
setInterval,
clearInterval,
}
mockGlobal.Module = {
onRuntimeInitialized: () => resolveInit(),
wasmBinary,
print: () => {},
printErr: () => {},
}
mockGlobal.self = mockGlobal
mockGlobal.self.location = { href: jsPath }
mockGlobal.WorkerGlobalScope = function () {}
mockGlobal.VTS_WASM_URL = `file://${wasmPath}`
mockGlobal.wasm_isaac_generate = (ptr, n) => {
const buf = new Uint8Array(mockGlobal.Module.HEAPU8.buffer, ptr, n)
capturedKeystream = new Uint8Array(buf) // copy view
}
try {
const context = vm.createContext(mockGlobal)
new vm.Script(jsContent, { filename: jsPath }).runInContext(context)
} catch (e) {
rejectInit(e)
}
;(async () => {
try {
await initPromise
if (!mockGlobal.Module.WxIsaac64 && mockGlobal.Module.asm && mockGlobal.Module.asm.WxIsaac64) {
mockGlobal.Module.WxIsaac64 = mockGlobal.Module.asm.WxIsaac64
}
if (!mockGlobal.Module.WxIsaac64) {
throw new Error('WxIsaac64 not found in WASM module')
}
capturedKeystream = null
const isaac = new mockGlobal.Module.WxIsaac64(key)
isaac.generate(size)
if (isaac.delete) isaac.delete()
if (!capturedKeystream) throw new Error('Failed to capture keystream')
const out = Buffer.from(capturedKeystream)
// Match WeFlow worker logic: reverse the captured Uint8Array.
out.reverse()
process.stdout.write(out.toString('base64'))
} catch (e) {
process.stderr.write(String(e && e.stack ? e.stack : e) + '\\n')
process.exit(1)
}
})()