bookworm-smart-assistant/lib/fingerprint.js

99 lines
3.2 KiB
JavaScript
Raw Permalink Normal View History

/**
* 设备指纹生成 - 跨平台 (v3.0.4: Win11 兼容)
* 基于: 主机名 + 用户名 + CPU ID + 磁盘序列号 + 架构
* 输出 SHA-256 hex (64 字符)
*
* v3.0.4: Win11 22H2+ 默认移除 wmic.exe, 改为三级 fallback:
* 1. PowerShell CIM cmdlet (Win10/Win11 通用)
* 2. wmic.exe ( Win10 残留)
* 3. 注册表 MachineGuid (任何 Windows 都有, 兜底)
*/
const crypto = require("crypto");
const os = require("os");
const fs = require("fs");
const { execSync } = require("child_process");
function safeExec(cmd) {
try {
return execSync(cmd, { encoding: "utf8", timeout: 5000, windowsHide: true }).toString();
} catch { return ""; }
}
// Windows 三级 fallback 查询
function winQuery(cimExpr, wmicArgs, regFallback) {
// 1. PowerShell CIM (最优先 - Win10/11 都原生支持)
const ps = safeExec(`powershell -NoProfile -NonInteractive -Command "${cimExpr.replace(/"/g, '\\"')}"`);
const psResult = ps.replace(/[\r\n]/g, "").trim();
if (psResult && psResult.length > 0) return psResult;
// 2. wmic.exe fallback (Win11 22H2+ 可能被移除, 先检测存在性)
const wmic = "C:\\Windows\\System32\\wbem\\wmic.exe";
if (fs.existsSync(wmic)) {
const out = safeExec(`"${wmic}" ${wmicArgs}`);
const lines = out.split(/\r?\n/).filter(l => /=.+/.test(l));
for (const l of lines) {
const v = l.split("=")[1]?.trim();
if (v && v.length > 0) return v;
}
}
// 3. 注册表兜底 (MachineGuid — 任何 Windows 一装系统就存在, 重装才变)
if (regFallback) {
const regOut = safeExec(`reg query "${regFallback.key}" /v "${regFallback.value}"`);
const m = regOut.match(/REG_SZ\s+(.+)/i);
if (m) return m[1].trim();
}
return "";
}
function cpuId() {
if (process.platform === "win32") {
return winQuery(
"(Get-CimInstance Win32_Processor).ProcessorId",
"cpu get ProcessorId /value",
{ key: "HKLM\\SOFTWARE\\Microsoft\\Cryptography", value: "MachineGuid" }
);
}
if (process.platform === "darwin") {
const out = safeExec("system_profiler SPHardwareDataType");
const m = out.match(/Hardware UUID:\s+([A-F0-9-]+)/);
return m ? m[1] : "";
}
// Linux
return safeExec("cat /etc/machine-id 2>/dev/null").trim();
}
function diskSerial() {
if (process.platform === "win32") {
return winQuery(
"(Get-CimInstance Win32_DiskDrive | Where-Object { $_.SerialNumber } | Select-Object -First 1).SerialNumber",
"diskdrive get SerialNumber /value",
{ key: "HKLM\\SOFTWARE\\Microsoft\\Cryptography", value: "MachineGuid" }
);
}
if (process.platform === "darwin") {
const out = safeExec("diskutil info /");
const m = out.match(/Volume UUID:\s+([A-F0-9-]+)/);
return m ? m[1] : "";
}
return safeExec("lsblk -no SERIAL 2>/dev/null | head -1").trim();
}
function fingerprint() {
const raw = [
os.hostname(),
os.userInfo().username,
cpuId(),
diskSerial(),
os.arch()
].join("::");
return crypto.createHash("sha256").update(raw).digest("hex");
}
module.exports = { fingerprint };
if (require.main === module) {
// 直接运行时打印指纹
console.log(fingerprint());
}