import { hash } from 'ohash' import si from 'systeminformation' /** * 硬件指纹质量等级 * - strong: 2+ 个强标识符可用(推荐用于生产授权) * - medium: 1 个强标识符可用(可用但不理想) * - weak: 无强标识符(仅适合开发/测试) */ export type FingerprintQuality = 'strong' | 'medium' | 'weak' /** * 标准化的系统信息(用于机器码生成) */ export type NormalizedSystemInfo = { /** 系统 UUID(最稳定的硬件标识符) */ systemUuid: string | null /** 系统序列号 */ systemSerial: string | null /** 主板序列号 */ baseboardSerial: string | null /** 主板制造商 */ baseboardManufacturer: string | null /** BIOS 版本 */ biosVersion: string | null /** BIOS 供应商 */ biosVendor: string | null /** CPU 品牌标识(用于质量评估) */ cpuBrand: string | null /** 主硬盘序列号(可选,高稳定性) */ primaryDiskSerial?: string | null } /** * 硬件指纹配置选项 */ export type HardwareFingerprintOptions = { /** * 缓存 TTL(毫秒),默认 10 分钟 * 硬件信息变化频率极低,缓存可大幅提升性能 */ cacheTtlMs?: number /** * 是否包含主硬盘序列号(默认 true) * 注意:在容器/虚拟机环境可能获取失败 */ includePrimaryDisk?: boolean } /** * 硬件指纹响应 */ export type HardwareFingerprintResult = { /** 机器码(HMAC-SHA256 哈希,64 字符十六进制) */ fingerprint: string /** 指纹质量等级 */ quality: FingerprintQuality /** 可用的强标识符数量 */ strongIdentifiersCount: number /** 生成时间戳 */ timestamp: number } // 缓存实例 let cache: { expiresAt: number value: HardwareFingerprintResult } | null = null // 防止并发重复请求 let inFlight: Promise | null = null /** * 计算指纹质量 */ function computeQuality(info: NormalizedSystemInfo): { quality: FingerprintQuality count: number } { const strongKeys = [ info.systemUuid, info.systemSerial, info.baseboardSerial, info.primaryDiskSerial, ].filter(Boolean).length if (strongKeys >= 2) return { quality: 'strong', count: strongKeys } if (strongKeys === 1) return { quality: 'medium', count: strongKeys } return { quality: 'weak', count: 0 } } /** * 安全地收集标准化系统信息(容错处理) */ async function collectNormalizedInfo( opts: HardwareFingerprintOptions, ): Promise { // 使用 Promise.allSettled 避免单点失败 const tasks = await Promise.allSettled([ si.uuid(), si.system(), si.baseboard(), si.bios(), si.cpu(), opts.includePrimaryDisk !== false ? si.diskLayout() : Promise.resolve([]), ]) const [uuidRes, systemRes, baseboardRes, biosRes, cpuRes, diskRes] = tasks const uuid = uuidRes.status === 'fulfilled' ? uuidRes.value : null const system = systemRes.status === 'fulfilled' ? systemRes.value : null const baseboard = baseboardRes.status === 'fulfilled' ? baseboardRes.value : null const bios = biosRes.status === 'fulfilled' ? biosRes.value : null const cpu = cpuRes.status === 'fulfilled' ? cpuRes.value : null // 提取主硬盘序列号(通常是第一个物理磁盘) let primaryDiskSerial: string | null = null if (diskRes.status === 'fulfilled' && Array.isArray(diskRes.value)) { const disks = diskRes.value as Array<{ serialNum?: string; type?: string }> const physicalDisk = disks.find( (d) => d.type !== 'USB' && d.serialNum && d.serialNum.trim(), ) primaryDiskSerial = physicalDisk?.serialNum?.trim() || null } return { // 系统级标识符(最稳定) systemUuid: (system?.uuid ?? uuid?.hardware ?? null) || null, systemSerial: (system?.serial ?? null) || null, // 主板标识符(次稳定) baseboardSerial: (baseboard?.serial ?? null) || null, baseboardManufacturer: (baseboard?.manufacturer ?? null) || null, // BIOS 信息(辅助识别) biosVersion: (bios?.version ?? null) || null, biosVendor: (bios?.vendor ?? null) || null, // CPU 信息(辅助识别) cpuBrand: (cpu?.brand ?? null) || null, // 磁盘序列号(可选,高稳定性) ...(opts.includePrimaryDisk !== false ? { primaryDiskSerial } : {}), } } /** /** * 获取硬件指纹(机器码) * * 适用场景:客户端部署的软件授权、机器绑定 * * 安全说明: * - 返回 SHA-256 哈希(Base64URL 编码,43 字符),不可逆推原始硬件信息 * - 使用 ohash 自动处理对象序列化和哈希 * - 客户端部署场景:客户可以看到代码,无法使用密钥加密 * - 安全性依赖硬件信息本身的不可伪造性(来自操作系统) * - 自动缓存减少系统调用开销 * * 稳定性: * - 优先使用系统 UUID、序列号等不易变更的标识符 * - 避免网络接口等易变信息 * - 容错处理,部分信息缺失不影响生成 * * @example * ```typescript * const result = await getHardwareFingerprint({ * cacheTtlMs: 600000, // 10 分钟 * includePrimaryDisk: true, * }) * * console.log(result.fingerprint) // "a3f5e8c2d1b4..." * console.log(result.quality) // "strong" * ``` */ export async function getHardwareFingerprint( opts: HardwareFingerprintOptions, ): Promise { const ttl = opts.cacheTtlMs ?? 10 * 60 * 1000 const now = Date.now() // 返回缓存结果 if (cache && cache.expiresAt > now) { return cache.value } // 防止并发重复请求 if (inFlight) { return inFlight } inFlight = (async () => { // 收集标准化信息 const info = await collectNormalizedInfo(opts) // 计算质量 const { quality, count } = computeQuality(info) // 使用 ohash 生成指纹(自动序列化 + SHA-256 + Base64URL) const fingerprint = hash({ v: 1, // 版本号,未来如需变更采集策略可递增 info, }) const result: HardwareFingerprintResult = { fingerprint, quality, strongIdentifiersCount: count, timestamp: now, } // 更新缓存 cache = { expiresAt: now + ttl, value: result } return result })().finally(() => { inFlight = null }) return inFlight } /** * 清除指纹缓存(用于测试或强制刷新) */ export function clearFingerprintCache(): void { cache = null inFlight = null }