2026-04-27 17:59:44 +08:00
|
|
|
/**
|
|
|
|
|
* 设备指纹生成 - 跨平台 (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());
|
|
|
|
|
}
|