import crypto from 'crypto'; import db from '../../config/database'; import { logger } from '../../utils/logger'; export interface NodeIdentity { nodeId: string; hardwareFingerprint: string; clientCertFingerprint?: string; // [CORE_SEC_07] mTLS 证书指纹 publicKey: string; status: 'PENDING' | 'TRUSTED' | 'REVOKED'; lastSeenAt: Date; } /** * [CORE_SEC_04] 零信任节点身份管理服务 * @description 结合硬件指纹与非对称加密,确保只有受信任的物理设备能接入 Hub */ export class NodeIdentityService { private static readonly TABLE_NAME = 'cf_node_identities'; /** * 注册/更新节点身份 (基于硬件指纹与 mTLS 证书) */ static async registerNode(params: { nodeId: string; hardwareFingerprint: string; clientCertFingerprint?: string; publicKey: string; }): Promise { const { nodeId, hardwareFingerprint, clientCertFingerprint, publicKey } = params; const existing = await db(this.TABLE_NAME).where({ node_id: nodeId }).first(); if (existing) { // 零信任校验:如果硬件指纹或证书指纹不匹配,拒绝更新 if (existing.hardware_fingerprint !== hardwareFingerprint) { logger.error(`[ZeroTrust] Node ID ${nodeId} hardware fingerprint mismatch!`); return false; } if (clientCertFingerprint && existing.client_cert_fingerprint && existing.client_cert_fingerprint !== clientCertFingerprint) { logger.error(`[ZeroTrust] Node ID ${nodeId} mTLS certificate mismatch! Potential spoofing.`); return false; } await db(this.TABLE_NAME).where({ node_id: nodeId }).update({ public_key: publicKey, client_cert_fingerprint: clientCertFingerprint || existing.client_cert_fingerprint, last_seen_at: new Date(), updated_at: new Date() }); } else { await db(this.TABLE_NAME).insert({ node_id: nodeId, hardware_fingerprint: hardwareFingerprint, client_cert_fingerprint: clientCertFingerprint, public_key: publicKey, status: 'PENDING', last_seen_at: new Date(), created_at: new Date(), updated_at: new Date() }); logger.info(`[ZeroTrust] New node registered: ${nodeId} (mTLS: ${!!clientCertFingerprint})`); } return true; } /** * 验证节点签名的请求负载 (Challenge-Response) */ static async verifyNodeSignature(nodeId: string, payload: any, signature: string): Promise { const node = await db(this.TABLE_NAME).where({ node_id: nodeId, status: 'TRUSTED' }).first(); if (!node) return false; try { const verifier = crypto.createVerify('SHA256'); verifier.update(JSON.stringify(payload)); return verifier.verify(node.public_key, signature, 'base64'); } catch (err) { return false; } } /** * 初始化数据库表 */ static async initTable() { const exists = await db.schema.hasTable(this.TABLE_NAME); if (!exists) { logger.info(`📦 Creating ${this.TABLE_NAME} table...`); await db.schema.createTable(this.TABLE_NAME, (table) => { table.string('node_id', 64).primary(); table.string('hardware_fingerprint', 128).notNullable(); table.string('client_cert_fingerprint', 128); table.text('public_key').notNullable(); table.string('status', 16).defaultTo('PENDING'); table.timestamp('last_seen_at'); table.timestamps(true, true); table.index(['hardware_fingerprint']); }); logger.info(`✅ Table ${this.TABLE_NAME} created`); } } }