// Detectorul Java: JCA getInstance("..."), SSLContext, protocoale activate, Bouncy Castle. import { argumente, imparteArgumente, valoareArgument, necunoscut } from './context.mjs'; import { hashCanonic, grupTls, curbaCanonica } from './catalog.mjs'; const TLSV = { TLSv1: '1.0', 'TLSv1.1': '1.1', 'TLSv1.2': '1.2', 'TLSv1.3': '1.3', SSLv3: 'ssl3', SSLv2Hello: 'ssl2', SSL: 'negotiated', TLS: 'negotiated', Default: 'negotiated' }; // transforma numele JCA intr-un activ de catalog, dupa clasa care il cere export function activJca(clasa, val, dupa = '', variabila = null) { const peVar = (metoda, rest) => (variabila ? new RegExp(`(? (x || '').trim()); const alg = alg0.toUpperCase(); const mod = mod0 ? mod0.toLowerCase() : undefined; const pad = pad0 ? pad0.toUpperCase() : ''; let m; if (alg === 'RSA') { const padding = /OAEP/.test(pad) ? 'oaep' : /PKCS1/.test(pad) ? 'pkcs1v15' : /NOPADDING/.test(pad) ? 'raw' : (pad ? 'other' : 'pkcs1v15'); const nota = pad ? undefined : 'Cipher "RSA" without padding means RSA/ECB/PKCS1Padding in the standard JCA providers.'; return { grup: 'RSA', primitiv: 'pke', padding, nota, functii: ['encrypt', 'decrypt'] }; } if ((m = /^AES(?:_(128|192|256))?$/.exec(alg))) { if (!mod) return { grup: 'CIPHER', nume: 'AES', param: m[1], mod: 'ecb', nota: 'Cipher "AES" without mode and padding means AES/ECB/PKCS5Padding in the standard JCA providers.', functii: ['encrypt', 'decrypt'] }; return { grup: 'CIPHER', nume: 'AES', param: m[1], mod: mod === 'nopadding' ? undefined : mod, functii: ['encrypt', 'decrypt'] }; } if (alg === 'DES') return { grup: 'CIPHER', nume: 'DES', mod, functii: ['encrypt', 'decrypt'] }; if (alg === 'DESEDE' || alg === 'TRIPLEDES') return { grup: 'CIPHER', nume: '3DES', mod, functii: ['encrypt', 'decrypt'] }; if (alg === 'RC4' || alg === 'ARCFOUR') return { grup: 'CIPHER', nume: 'RC4', functii: ['encrypt', 'decrypt'] }; if (alg === 'RC2') return { grup: 'CIPHER', nume: 'RC2', functii: ['encrypt', 'decrypt'] }; if (alg === 'BLOWFISH') return { grup: 'CIPHER', nume: 'Blowfish', mod, functii: ['encrypt', 'decrypt'] }; if (alg === 'CHACHA20-POLY1305') return { grup: 'CIPHER', nume: 'ChaCha20-Poly1305', functii: ['encrypt', 'decrypt'] }; if (alg === 'CHACHA20') return { grup: 'CIPHER', nume: 'ChaCha20', functii: ['encrypt', 'decrypt'] }; if (/^PBEWITH(MD5|SHA1)AND(DES|TRIPLEDES|RC2|RC4)/.test(alg)) return { grup: 'CIPHER', nume: /TRIPLEDES/.test(alg) ? '3DES' : /RC2/.test(alg) ? 'RC2' : /RC4/.test(alg) ? 'RC4' : 'DES', nota: `${v} derives the key with a weak hash.` }; if (/^ECIES/.test(alg)) return { grup: 'ECDH', nume: 'ECIES', primitiv: 'pke', functii: ['encrypt', 'decrypt'] }; return { grup: 'UNKNOWN', motiv: `Cipher transformation "${v}" is not in this tool's catalog.` }; } // nume post-cuantice in JCA sau Bouncy Castle export function pqNume(v) { const t = String(v).trim(); let m; if ((m = /^ML-?KEM(?:-(512|768|1024))?$/i.exec(t))) return { grup: 'MLKEM', param: m[1] }; if ((m = /^ML-?DSA(?:-(44|65|87))?$/i.exec(t))) return { grup: 'MLDSA', param: m[1] }; if ((m = /^SLH-?DSA(?:-(SHA2|SHAKE)-(128|192|256)([sfSF]))?$/i.exec(t))) return { grup: 'SLHDSA', param: m[1] ? `${m[1].toUpperCase()}-${m[2]}${m[3].toLowerCase()}` : undefined }; if ((m = /^(?:Falcon|FN-DSA)(?:-(512|1024))?$/i.exec(t))) return { grup: 'FALCON', param: m[1] }; if (/^(Kyber\d*|Dilithium\d*|SPHINCSPlus|SPHINCS\+)$/i.test(t)) return { grup: 'PREPQ', nume: t, primitiv: /kyber/i.test(t) ? 'kem' : 'signature' }; if (/^(XMSS|XMSSMT|XMSS\^MT|LMS|HSS)$/i.test(t)) return { grup: 'HASHSIG', nume: t.toUpperCase() }; if (/^(Rainbow|SIKE)$/i.test(t)) return { grup: 'BROKENPQ', nume: t, primitiv: /rainbow/i.test(t) ? 'signature' : 'kem' }; if (/^HQC(-\d+)?$/i.test(t)) return { grup: 'HQC', nume: t.toUpperCase() }; return null; } const BC_CLASA = [ [/^(ECDSASigner|ECNRSigner|DSTU4145Signer)$/, { grup: 'ECDSA' }], [/^(DSASigner)$/, { grup: 'DSA' }], [/^(RSADigestSigner|PSSSigner|RSAEngine|RSABlindedEngine|OAEPEncoding|PKCS1Encoding|RSAKeyPairGenerator|ISO9796d2Signer)$/, { grup: 'RSA' }], [/^(ECKeyPairGenerator|ECNamedCurveTable|SECNamedCurves|ECDomainParameters)$/, { grup: 'EC' }], [/^(ECDHBasicAgreement|ECDHCBasicAgreement|ECDHUnifiedAgreement)$/, { grup: 'ECDH' }], [/^(DHBasicAgreement|DHAgreement|DHKeyPairGenerator)$/, { grup: 'DH' }], [/^(Ed25519Signer|Ed25519ctxSigner|Ed25519phSigner|Ed25519KeyPairGenerator)$/, { grup: 'EDDSA', nume: 'Ed25519' }], [/^(Ed448Signer|Ed448KeyPairGenerator)$/, { grup: 'EDDSA', nume: 'Ed448' }], [/^(X25519Agreement|X25519KeyPairGenerator)$/, { grup: 'XDH', nume: 'X25519' }], [/^(X448Agreement|X448KeyPairGenerator)$/, { grup: 'XDH', nume: 'X448' }], [/^SecP256K1Curve$/, { grup: 'SECP256K1' }], [/^MD5Digest$/, { grup: 'HASH', hash: 'MD5' }], [/^SHA1Digest$/, { grup: 'HASH', hash: 'SHA1' }], [/^SHA256Digest$/, { grup: 'HASH', hash: 'SHA256' }], [/^SHA512Digest$/, { grup: 'HASH', hash: 'SHA512' }], [/^(DESEngine)$/, { grup: 'CIPHER', nume: 'DES' }], [/^(DESedeEngine)$/, { grup: 'CIPHER', nume: '3DES' }], [/^(RC4Engine)$/, { grup: 'CIPHER', nume: 'RC4' }], [/^(BlowfishEngine)$/, { grup: 'CIPHER', nume: 'Blowfish' }], [/^(AESEngine|AESFastEngine|AESLightEngine)$/, { grup: 'CIPHER', nume: 'AES' }], ]; function bcActiv(cale) { const clasa = cale.split('.').pop(); let m; if ((m = /^(MLKEM|MLDSA|SLHDSA|Falcon|Kyber|Dilithium|SPHINCSPlus|XMSS|XMSSMT|LMS|HSS|Rainbow|SIKE|HQC|NTRU|NTRUPrime|BIKE|Frodo|CMCE|Picnic|Saber)/.exec(clasa))) { const fam = m[1]; const map = { MLKEM: 'ML-KEM', MLDSA: 'ML-DSA', SLHDSA: 'SLH-DSA', SPHINCSPlus: 'SPHINCSPlus', XMSSMT: 'XMSSMT' }; const pq = pqNume(map[fam] || fam); if (pq) return pq; return { grup: 'UNKNOWN', motiv: `Bouncy Castle post-quantum class ${clasa}: scheme "${fam}" is not classified by this tool (not a finalized NIST standard).` }; } if (/\.pqc\./.test(cale)) { if (/BouncyCastlePQCProvider$/.test(clasa)) return { grup: 'UNKNOWN', motiv: 'Bouncy Castle PQC provider registered; the scheme is chosen elsewhere (not visible in this import).' }; return { grup: 'UNKNOWN', motiv: `Bouncy Castle post-quantum package class ${clasa}; scheme not recognized by this tool.` }; } for (const [re, act] of BC_CLASA) if (re.test(clasa)) return act; return null; } // Variabila din `v = ` pe acelasi rand, citita INAPOI de la pozitie (ce dadea /([A-Za-z_$][\w$]*)\s*=\s*$/ pe textul randului // de dinainte). Forma veche taia la fiecare apel tot randul pana la pozitie, deci un rand lung cu multe apeluri costa patratic // (2026-09-29, revizuirea adversariala); cititul inapoi se opreste la primul caracter care nu poate face parte din tipar. export function variabilaAtribuita(c, pos) { const sp = (ch) => ch !== '\n' && /\s/.test(ch); let j = pos - 1; while (j >= 0 && sp(c[j])) j--; if (j < 0 || c[j] !== '=') return null; j--; while (j >= 0 && sp(c[j])) j--; const sf = j + 1; while (j >= 0 && /[\w$]/.test(c[j])) j--; let st = j + 1; while (st < sf && /[0-9]/.test(c[st])) st++; return st < sf ? c.slice(st, sf) : null; } export function detecteazaJava(ctx) { const c = ctx.code; const consumate = new Set(); for (const m of ctx.potriviri(/(? TLSV[x[1]]).filter(Boolean); for (const x of vers) { const ver = TLSV[x[1]]; if (!ver) continue; const rol = ver === '1.2' && lista.includes('1.3') ? 'min' : 'only'; ctx.adauga(a.start + x.index, 'setEnabledProtocols', 'config', { grup: 'TLS', param: ver, rol }, { bucata: `"${x[1]}"` }); } } // proprietati de sistem ale JSSE for (const m of ctx.potriviri(/(?