'use strict'; // Proba "Proof of everything": pentru FIECARE fel construieste un plic, il verifica cu ACELASI verificator AIP-23 (zero cod nou), si // controale negative: continut atins dupa hash -> INVALID; camp obligatoriu lipsa -> eroare la constructie; niciun continut brut in plic. // node proba-proof-kinds.mjs -> 0 toate cum trebuia, 1 altfel import fs from 'node:fs'; import crypto from 'node:crypto'; import os from 'node:os'; import path from 'node:path'; import { execFileSync } from 'node:child_process'; import { fileURLToPath } from 'node:url'; import { buildProof, KINDS } from './proof-kinds.mjs'; const AICI = path.dirname(fileURLToPath(import.meta.url)); const VERIFY = process.env.AERE_VERIFY_PROOF ? path.resolve(process.env.AERE_VERIFY_PROOF) : path.resolve(AICI, '..', 'aere-proof-protocol', 'verify.mjs'); if (!fs.existsSync(VERIFY)) { console.log(`NEMASURAT: verificatorul AIP-23 nu e la ${VERIFY}; dati AERE_VERIFY_PROOF (de ex. verify-proof.mjs din aere-node/tools)`); process.exit(2); } const T = fs.mkdtempSync(path.join(os.tmpdir(), 'pk-')); let rele = 0; const cer = (n, c) => { console.log(` [${c ? 'OK ' : 'RAU '}] ${n}`); if (!c) rele++; }; function verdict(plicPath) { try { return JSON.parse(execFileSync(process.execPath, [VERIFY, plicPath, '--json'], { encoding: 'utf8' })).verdict; } catch (e) { try { return JSON.parse((e.stdout || '')).verdict; } catch { return '?'; } } } // intrari de proba pentru fiecare fel (continut brut, ca sa verific ca nu se scurge) const BRUT = 'CONTINUT-BRUT-BRUT-42'; const INTRARI = { data: { name: 'raport.csv', content: BRUT, createdAt: '2026-09-26T09:00:00Z' }, execution: { program: 'aere-node', input: BRUT, output: BRUT + 'o', exitCode: 0, createdAt: '2026-09-26T09:00:00Z' }, identity: { subjectId: 'agent-1', publicKey: BRUT, method: 'ml-dsa-65', createdAt: '2026-09-26T09:00:00Z' }, compliance: { subject: 'org-x', policy: 'pq-ready', result: 'pass', evidence: BRUT, createdAt: '2026-09-26T09:00:00Z' }, runtime: { host: 'h1', artifactContent: BRUT, attested: BRUT, matches: true, createdAt: '2026-09-26T09:00:00Z' }, location: { subject: 'srv-eu', region: 'eu-central', evidence: BRUT, createdAt: '2026-09-26T09:00:00Z' }, device: { deviceId: 'dev-9', attestation: BRUT, publicKey: BRUT, posture: 'secure-boot', createdAt: '2026-09-26T09:00:00Z' }, payment: { from: '0xa', to: '0xb', amount: '100', asset: 'AERE', tx: BRUT, createdAt: '2026-09-26T09:00:00Z' }, ownership: { owner: '0xowner', assetId: 'nft-7', asset: BRUT, createdAt: '2026-09-26T09:00:00Z' }, time: { subject: BRUT, source: 'aere-anchor', at: '2026-09-26T09:00:00Z', createdAt: '2026-09-26T09:00:00Z' }, block: { blockHash: '0x' + 'ab'.repeat(32), stateRoot: '0x' + 'cd'.repeat(32), anchorHeight: 20255488, certificateDigest: '0x' + 'ef'.repeat(32), createdAt: '2026-09-26T09:00:00Z' }, authorization: { grantor: 'org-x', grantee: 'agent-7', scope: 'payments:send<=100', policy: BRUT, expiresAt: '2026-12-31T00:00:00Z', createdAt: '2026-09-28T09:00:00Z' }, settlement: { chainId: 2800, txHash: '0x' + '12'.repeat(32), blockHash: '0x' + '34'.repeat(32), from: '0xa', to: '0xb', amount: '100', asset: 'AERE', instruction: BRUT, createdAt: '2026-09-28T09:00:00Z' }, provenance: { subject: BRUT, parents: [BRUT + '1', BRUT + '2'], process: BRUT + 'p', actor: 'build-bot', createdAt: '2026-09-28T09:00:00Z' }, }; try { cer('schema acopera cele 14 feluri (10 + bloc + autorizare, decontare, provenienta)', KINDS.length >= 14 && ['authorization', 'settlement', 'provenance'].every((k) => KINDS.includes(k))); for (const k of KINDS) { // fiecare fel se judeca separat: un fel care nu se mai poate construi e un RAU numit, nu o exceptie care opreste proba (2026-09-28) let plic; try { plic = buildProof(k, INTRARI[k]); } catch (e) { cer(`${k}: constructia a cazut (${e.message})`, false); continue; } const f = path.join(T, k + '.json'); fs.writeFileSync(f, JSON.stringify(plic, null, 1)); const v = verdict(f); const faraBrut = !JSON.stringify(plic).includes(BRUT); cer(`${k}: verificatorul AIP-23 il valideaza si nu contine continut brut`, v === 'VALID' && faraBrut); } // CONTROL NEGATIV 1: statement atins dupa hash -> INVALID (pe 'data') const p = buildProof('data', INTRARI.data); p.statement.name = 'ALTCEVA'; const fr = path.join(T, 'rau.json'); fs.writeFileSync(fr, JSON.stringify(p, null, 1)); cer('CONTROL: statement schimbat dupa hash -> INVALID', verdict(fr) === 'INVALID'); // CONTROL NEGATIV 2: camp obligatoriu lipsa -> eroare la constructie let aAruncat = false; try { buildProof('data', { name: 'x', createdAt: '2026-09-26T09:00:00Z' }); } catch { aAruncat = true; } cer('CONTROL: camp obligatoriu lipsa (sha256) -> eroare la constructie', aAruncat); // CONTROL NEGATIV 3: fel necunoscut -> eroare let aAruncat2 = false; try { buildProof('inexistent', { createdAt: '2026-09-26T09:00:00Z' }); } catch { aAruncat2 = true; } cer('CONTROL: fel necunoscut -> eroare', aAruncat2); // 2026-09-28: felurile noi isi refuza formele gresite la constructie, nu produc un plic gresit const arunca = (f) => { try { f(); return false; } catch { return true; } }; cer('CONTROL: decontare cu txHash care nu e hash de 32 de octeti -> eroare', arunca(() => buildProof('settlement', { ...INTRARI.settlement, txHash: '0x1234' }))); cer('CONTROL: provenienta cu lista de parinti goala -> eroare', arunca(() => buildProof('provenance', { ...INTRARI.provenance, parents: [] }))); cer('CONTROL: autorizare fara scope -> eroare', arunca(() => buildProof('authorization', { ...INTRARI.authorization, scope: undefined }))); const pv = buildProof('provenance', INTRARI.provenance); cer('provenienta: fiecare parinte e digestul continutului lui, in ordine', pv.statement.parents.length === 2 && pv.statement.parents[0] === '0x' + crypto.createHash('sha256').update(BRUT + '1', 'utf8').digest('hex')); // OCTETII unui Buffer (2026-09-27): digestul continutului dat ca Buffer = sha256 al octetilor (cel pe care il reface sha256sum pe // fisier) = digestul aceluiasi continut dat ca sir. Pana azi un Buffer se hashuia ca JSON {"type":"Buffer",...}. const oct = Buffer.from('ARTEFACT-DESFASURAT-\u0000\u00ff', 'latin1'); const asteptat = '0x' + crypto.createHash('sha256').update(oct).digest('hex'); const pb = buildProof('data', { name: 'a', content: oct, createdAt: '2026-09-26T09:00:00Z' }); const pu = buildProof('data', { name: 'a', content: new Uint8Array(oct), createdAt: '2026-09-26T09:00:00Z' }); const ps = buildProof('data', { name: 'a', content: 'abc', createdAt: '2026-09-26T09:00:00Z' }); cer('Buffer/Uint8Array: digestul = sha256 al octetilor (reproductibil cu sha256sum)', pb.statement.sha256 === asteptat && pu.statement.sha256 === asteptat); cer('sirurile raman ca inainte (vectorii publicati neschimbati)', ps.statement.sha256 === '0x' + crypto.createHash('sha256').update('abc', 'utf8').digest('hex')); } finally { fs.rmSync(T, { recursive: true, force: true }); } const total = KINDS.length + 10; console.log(`\nProof of everything: ${total - rele}/${total} cum trebuia (${KINDS.length} feluri + 6 controale negative + acoperire + Buffer + parinti)`); process.exit(rele ? 1 : 0);