import { NfcAntiTamperService, generateCardOfflineSeal, verifyCardOfflineSeal, OfflineCardPayload, verifyOfflineCardPayload, } from '../../../src/modules/nfc/service/anti-tamper'; describe('Point 44: NFC 实体卡离线数字防伪防篡改签章与硬件出厂封印', () => { let service: NfcAntiTamperService; const mockUid = '04A1B2C3D4E5F6'; const mockCardId = 2002; const mockSecret = 'nfc-secret-key-gitex-2026-dubai-omnicard'; const mockFactoryKey = 'factory-master-key-secure-hardware-seal'; const mockBatchNo = 'BATCH-202609-UAE-001'; beforeEach(() => { service = new NfcAntiTamperService(); }); describe('1. 硬件物理出厂封印 (generateCardOfflineSeal & verifyCardOfflineSeal)', () => { it('应基于 UID、批次号与工厂母密钥生成不可逆 SHA-256 硬件封印哈希', () => { const seal = generateCardOfflineSeal(mockUid, mockBatchNo, mockFactoryKey); expect(typeof seal).toBe('string'); expect(seal).toHaveLength(64); expect(/^[0-9a-f]{64}$/i.test(seal)).toBe(true); // 验证封印通过 const isSealValid = verifyCardOfflineSeal(mockUid, mockBatchNo, seal, mockFactoryKey); expect(isSealValid).toBe(true); }); it('篡改 UID、批次号或封印哈希时应严密拒绝', () => { const seal = generateCardOfflineSeal(mockUid, mockBatchNo, mockFactoryKey); // 篡改 UID expect(verifyCardOfflineSeal('04FFFFFFFFFFFF', mockBatchNo, seal, mockFactoryKey)).toBe(false); // 篡改批次号 expect(verifyCardOfflineSeal(mockUid, 'BATCH-FAKED', seal, mockFactoryKey)).toBe(false); // 篡改签名封印 expect(verifyCardOfflineSeal(mockUid, mockBatchNo, seal.replace('a', 'b'), mockFactoryKey)).toBe(false); }); it('参数缺失时抛出明确保护异常', () => { expect(() => generateCardOfflineSeal('', mockBatchNo, mockFactoryKey)).toThrow(); expect(() => generateCardOfflineSeal(mockUid, '', mockFactoryKey)).toThrow(); expect(() => generateCardOfflineSeal(mockUid, mockBatchNo, '')).toThrow(); }); }); describe('2. 离线碰一碰数据包快速验签 (verifyOfflineCardPayload)', () => { it('合法离线数据包在无网络状态下应成功通过验签', () => { const ts = Date.now(); const token = service.generateDeviceToken(mockUid, mockCardId, mockSecret, ts); const seal = generateCardOfflineSeal(mockUid, mockBatchNo, mockFactoryKey); const payload: OfflineCardPayload = { uid: mockUid, cardId: mockCardId, batchNo: mockBatchNo, seal, token, }; const result = verifyOfflineCardPayload(payload, mockSecret, mockFactoryKey); expect(result.valid).toBe(true); expect(result.isAuthenticNfc).toBe(true); expect(result.reason).toBeUndefined(); }); it('离线防伪 Token 伪造时应准确识破', () => { const seal = generateCardOfflineSeal(mockUid, mockBatchNo, mockFactoryKey); const fakePayload: OfflineCardPayload = { uid: mockUid, cardId: mockCardId, batchNo: mockBatchNo, seal, token: `${Date.now()}.0000000000000000000000000000000000000000000000000000000000000000`, }; const result = verifyOfflineCardPayload(fakePayload, mockSecret, mockFactoryKey); expect(result.valid).toBe(false); expect(result.reason).toMatch(/签名|篡改|invalid/i); }); }); describe('3. 时钟漂移与时序攻击防护 (Clock Drift Tolerance)', () => { it('在合理漂移容差内 (30秒) 允许通过', () => { const futureTs = Date.now() + 15 * 1000; // 稍超前 15 秒 (网络或卡内时钟微偏) const token = service.generateDeviceToken(mockUid, mockCardId, mockSecret, futureTs); // 设置 30 秒容差 const res = service.verifyDeviceToken(mockUid, mockCardId, token, mockSecret, 300000, 30000); expect(res.valid).toBe(true); }); it('严重超前于未来时间戳的令牌应被坚决拦截', () => { const futureTs = Date.now() + 120 * 1000; // 超前 2 分钟 const token = service.generateDeviceToken(mockUid, mockCardId, mockSecret, futureTs); const res = service.verifyDeviceToken(mockUid, mockCardId, token, mockSecret, 300000, 30000); expect(res.valid).toBe(false); expect(res.reason).toMatch(/未来|clock drift/i); }); }); });