import test from 'node:test'; import assert from 'node:assert/strict'; import { createHash, generateKeyPairSync, sign } from 'node:crypto'; import { EncryptedNodeKeyStoreProofSource, type NodeKeyStoreAdapter } from './node-keystore-bridge.js'; import { createNodePossessionChallenge, verifyNodePossessionResponse } from './node-possession-proof.js'; import { nodeRegistrationClaimSigningBytes, parseNodeRegistrationEndpointRegistry, resolveNodeRegistrationEndpoint, verifyNodeRegistrationClaim, } from './node-registration.js'; const NOW = 1_786_291_200_000; const DOMAIN_ID = 'DOM-FIFTH-0001'; const NODE_ID = 'LOCAL-001'; const registrationKeys = generateKeyPairSync('ed25519'); const nodeKeys = generateKeyPairSync('ed25519'); const nodePublicKeyPem = nodeKeys.publicKey.export({ format: 'pem', type: 'spki' }).toString(); const nodePrivateKeyPkcs8 = nodeKeys.privateKey.export({ format: 'der', type: 'pkcs8' }); const fingerprint = createHash('sha256') .update(nodeKeys.publicKey.export({ format: 'der', type: 'spki' })) .digest('hex'); function verifiedRegistration() { const registry = parseNodeRegistrationEndpointRegistry({ endpoints: [{ algorithm: 'Ed25519', domainIds: [DOMAIN_ID], endpointId: 'GH-NODE-REG-001', nodeTypes: ['local-terminal'], publicKeyPem: registrationKeys.publicKey.export({ format: 'pem', type: 'spki' }).toString(), signerId: 'GH-NODE-REG-SIGNER-001', status: 'ACTIVE', url: 'https://guanghulab.com/api/ai/v1/node-registrations/claims', }], registryId: 'GH-AIOS-NODE-REGISTRATION-ENDPOINTS-001', schema: 'gh-aios.node-registration-endpoints/v1', state: 'CURRENT', version: '1.0.0', }, { repositoryId: 'REPO-012', sourceCommit: 'a'.repeat(40), sourceUrl: `https://guanghulab.com/code/bingshuo/guanghu-ice-heart/raw/commit/${'a'.repeat(40)}/routing/node-registration-endpoints.json`, }); const endpoint = resolveNodeRegistrationEndpoint(registry, { domainId: DOMAIN_ID, nodeType: 'local-terminal' }); assert.ok(endpoint); const payload = { accountId: 'bingshuo', claimId: 'NODE-CLAIM-001', domainId: DOMAIN_ID, endpointId: endpoint.endpointId, expiresAt: NOW + 120_000, issuedAt: NOW - 1_000, nodeId: NODE_ID, nodeKeyFingerprint: fingerprint, nodeType: 'local-terminal' as const, schema: 'gh-aios.node-registration-claim/v1' as const, signerId: endpoint.signerId, }; return verifyNodeRegistrationClaim({ ...payload, signature: sign(null, nodeRegistrationClaimSigningBytes(payload), registrationKeys.privateKey).toString('base64'), }, { accountId: payload.accountId, domainId: DOMAIN_ID, nodeId: NODE_ID, nodeType: 'local-terminal', }, endpoint, NOW); } function keyRecord(overrides: Record = {}) { return { encryptedPrivateKeyPkcs8: Buffer.from('encrypted-test-record').toString('base64'), nodeId: NODE_ID, nodeKeyFingerprint: fingerprint, nodeType: 'local-terminal', publicKeyPem: nodePublicKeyPem, schema: 'gh-aios.node-keystore-record/v1', ...overrides, }; } function adapter(overrides: Partial = {}): NodeKeyStoreAdapter { return { async decryptPrivateKeyPkcs8() { return Buffer.from(nodePrivateKeyPkcs8); }, isAvailable() { return true; }, async readRecord() { return keyRecord(); }, ...overrides, }; } function challenge(id = 'NODE-CHALLENGE-KEYSTORE-001') { return createNodePossessionChallenge(verifiedRegistration(), NOW, id, 'A'.repeat(43)); } test('signs only an active challenge with the enrolled matching Ed25519 key', async () => { const issued = challenge(); const source = new EncryptedNodeKeyStoreProofSource(adapter(), () => NOW + 1); const response = await source.prove(issued); assert.ok(response); assert.deepEqual(Object.keys(response).sort(), ['challengeId', 'publicKeyPem', 'schema', 'signature']); assert.ok(verifyNodePossessionResponse(response, issued, verifiedRegistration(), NOW + 2)); }); test('returns no proof when storage is unavailable or no enrollment exists', async () => { const issued = challenge('NODE-CHALLENGE-KEYSTORE-002'); assert.equal(await new EncryptedNodeKeyStoreProofSource(adapter({ isAvailable: () => false }), () => NOW + 1).prove(issued), null); assert.equal(await new EncryptedNodeKeyStoreProofSource(adapter({ readRecord: async () => null }), () => NOW + 1).prove(issued), null); }); test('rejects copied challenges, unknown record fields and node binding mismatches', async () => { const issued = challenge('NODE-CHALLENGE-KEYSTORE-003'); assert.equal(await new EncryptedNodeKeyStoreProofSource(adapter(), () => NOW + 1).prove({ ...issued }), null); assert.equal(await new EncryptedNodeKeyStoreProofSource(adapter({ readRecord: async () => keyRecord({ extra: true }) }), () => NOW + 1).prove(issued), null); assert.equal(await new EncryptedNodeKeyStoreProofSource(adapter({ readRecord: async () => keyRecord({ nodeId: 'OTHER-NODE' }) }), () => NOW + 1).prove(issued), null); }); test('rejects malformed encryption payloads and mismatched private keys', async () => { const issued = challenge('NODE-CHALLENGE-KEYSTORE-004'); assert.equal(await new EncryptedNodeKeyStoreProofSource(adapter({ readRecord: async () => keyRecord({ encryptedPrivateKeyPkcs8: '***' }) }), () => NOW + 1).prove(issued), null); const other = generateKeyPairSync('ed25519').privateKey.export({ format: 'der', type: 'pkcs8' }); assert.equal(await new EncryptedNodeKeyStoreProofSource(adapter({ decryptPrivateKeyPkcs8: async () => Buffer.from(other) }), () => NOW + 1).prove(issued), null); }); test('wipes the decrypted temporary key bytes after signing', async () => { const issued = challenge('NODE-CHALLENGE-KEYSTORE-005'); const decrypted = Buffer.from(nodePrivateKeyPkcs8); const source = new EncryptedNodeKeyStoreProofSource(adapter({ decryptPrivateKeyPkcs8: async () => decrypted }), () => NOW + 1); assert.ok(await source.prove(issued)); assert.ok(decrypted.every(byte => byte === 0)); });