aere-quantum/pq-kms/test/control-negativ-hsm-incredere.mjs

59 lines
4.6 KiB
JavaScript

// test/control-negativ-hsm-incredere.mjs (2026-09-29): controlul negativ al probei H1 (proba-hsm-incredere.mjs). Trei stari pe caz:
// PRINS (proba a rulat pana la capat si a iesit rosie pe verificarea numita), SCAPAT, STRICAT (copia nu s-a incarcat / proba nu a rulat).
// V0 modulul de DINAINTE de reparatie (HEAD-ul lui git la momentul scrierii: `git show <rev>:.../hsm-radacina.mjs`) -> rosu pe H1
// P1 verificarea bibliotecii scoasa cu o conditie falsa la rulare -> rosu pe biblioteca straina
// P2 verificarea variabilei PIN-ului scoasa cu o conditie falsa la rulare -> rosu pe jetonul API ca PIN
// Copiile stau LANGA original (./kms.mjs trebuie sa se rezolve) si se sterg la sfarsit; originalul trebuie sa ramana octet cu octet.
// node test/control-negativ-hsm-incredere.mjs -> 0 toate prinse, 1 unul scapa, 2 STRICAT
import crypto from 'node:crypto';
import fs from 'node:fs';
import path from 'node:path';
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
const AICI = path.dirname(fileURLToPath(import.meta.url));
const SRC = path.join(AICI, '..', 'hsm-radacina.mjs');
const PROBA = path.join(AICI, 'proba-hsm-incredere.mjs');
const sha = (f) => crypto.createHash('sha256').update(fs.readFileSync(f)).digest('hex');
const inainte = sha(SRC);
const REV_VECHE = process.env.AERE_HSM_REV_VECHE || '7f2e7182';
let prinse = 0, stricate = 0, total = 0;
function caz(id, text, tinta) {
total++;
const copie = path.join(AICI, '..', `.plantat-hsm-${id}.mjs`);
try {
fs.writeFileSync(copie, text);
const r = spawnSync(process.execPath, [PROBA], { encoding: 'utf8', env: { ...process.env, AERE_HSM_MODUL_SUB_PROBA: copie } });
const out = (r.stdout || '') + (r.stderr || '');
if (!/increderea in fisierul sigilat \(H1\): \d+\/\d+/.test(out)) { stricate++; console.log(` STRICAT ${id}: proba nu a ajuns la capat (${out.trim().split('\n').pop().slice(0, 120)})`); return; }
if (!/\[OK \] CONTROL POZITIV/.test(out)) { stricate++; console.log(` STRICAT ${id}: controlul pozitiv al probei nu a trecut pe copie`); return; }
const rosii = out.split('\n').filter((l) => l.includes('[RAU ]'));
if (r.status === 1 && rosii.some((l) => l.includes(tinta))) { prinse++; console.log(` PRINS ${id}: ${rosii.length} verificari rosii, intre ele "${tinta}"`); }
else console.log(` SCAPAT ${id}: cod ${r.status}, "${tinta}" nu e rosie`);
} finally { fs.rmSync(copie, { force: true }); }
}
const inlocuieste = (t, a, b) => { if (t.split(a).length !== 2) return null; return t.replace(a, b); };
// V0: codul vechi, din git (octetii comisi, fara conversia autocrlf)
// In depozitul public (alt istoric) codul de dinainte nu exista: V0 se sare, spus, si nu se numara; in depozitul de lucru trebuie sa ruleze.
const CALE_VECHE = `${REV_VECHE}:cloud-gateway/pq-kms/hsm-radacina.mjs`;
const exista = spawnSync('git', ['cat-file', '-e', CALE_VECHE], { cwd: path.join(AICI, '..'), encoding: 'utf8' }).status === 0;
if (!exista) console.log(` SARIT V0: codul de dinainte de reparatie (${REV_VECHE}) nu e in istoricul acestui depozit; NEMASURAT aici`);
else {
const g = spawnSync('git', ['-c', 'core.autocrlf=false', 'show', CALE_VECHE], { cwd: path.join(AICI, '..'), encoding: 'utf8' });
if (g.status !== 0 || !g.stdout.includes('export function deschideRadacina')) { stricate++; total++; console.log(' STRICAT V0: nu citesc modulul vechi din git (' + REV_VECHE + ')'); }
else caz('V0', g.stdout, 'biblioteca din fisier, alta decat AERE_HSM_MODULE');
}
const nou = fs.readFileSync(SRC, 'utf8');
const p1 = inlocuieste(nou, "if (sig.modul !== permis) throw", "if (sig.modul !== permis && process.env.AERE_PLANTA_NICIODATA === 'da') throw");
if (!p1) { stricate++; total++; console.log(' STRICAT P1: ancora nu apare exact o data'); } else caz('P1', p1, 'biblioteca din fisier, alta decat AERE_HSM_MODULE');
const p2 = inlocuieste(nou, "if (sig.pinEnv !== undefined && sig.pinEnv !== PIN_ENV) throw", "if (sig.pinEnv !== undefined && sig.pinEnv !== PIN_ENV && process.env.AERE_PLANTA_NICIODATA === 'da') throw");
if (!p2) { stricate++; total++; console.log(' STRICAT P2: ancora nu apare exact o data'); } else caz('P2', p2, 'alta variabila drept PIN');
const ramase = fs.readdirSync(path.join(AICI, '..')).filter((f) => f.startsWith('.plantat-hsm-'));
if (sha(SRC) !== inainte || ramase.length) { stricate++; console.log(' STRICAT originalul s-a schimbat sau au ramas copii: ' + ramase.join(',')); }
console.log(`\ncontrolul negativ H1: prinse ${prinse}/${total}, stricate ${stricate}`);
process.exitCode = stricate ? 2 : prinse === total ? 0 : 1;