/** * CLI script to decrypt FIEL credentials from filesystem backup. * Usage: FIEL_ENCRYPTION_KEY= npx tsx scripts/decrypt-fiel.ts * * Decrypted files are written to /tmp/horux-fiel-/ and auto-deleted after 30 minutes. */ import { readFile, writeFile, mkdir, rm } from 'fs/promises'; import { join } from 'path'; import { createDecipheriv, createHash } from 'crypto'; const FIEL_PATH = process.env.FIEL_STORAGE_PATH || '/var/horux/fiel'; const FIEL_KEY = process.env.FIEL_ENCRYPTION_KEY; const rfc = process.argv[2]; if (!rfc) { console.error('Usage: FIEL_ENCRYPTION_KEY= npx tsx scripts/decrypt-fiel.ts '); process.exit(1); } if (!FIEL_KEY) { console.error('Error: FIEL_ENCRYPTION_KEY environment variable is required'); process.exit(1); } function deriveKey(): Buffer { return createHash('sha256').update(FIEL_KEY!).digest(); } function decryptBuffer(encrypted: Buffer, iv: Buffer, tag: Buffer): Buffer { const key = deriveKey(); const decipher = createDecipheriv('aes-256-gcm', key, iv); decipher.setAuthTag(tag); return Buffer.concat([decipher.update(encrypted), decipher.final()]); } async function main() { const fielDir = join(FIEL_PATH, rfc.toUpperCase()); const outputDir = `/tmp/horux-fiel-${rfc.toUpperCase()}`; console.log(`Reading encrypted FIEL from: ${fielDir}`); // Read encrypted certificate const cerEnc = await readFile(join(fielDir, 'certificate.cer.enc')); const cerIv = await readFile(join(fielDir, 'certificate.cer.iv')); const cerTag = await readFile(join(fielDir, 'certificate.cer.tag')); // Read encrypted private key const keyEnc = await readFile(join(fielDir, 'private_key.key.enc')); const keyIv = await readFile(join(fielDir, 'private_key.key.iv')); const keyTag = await readFile(join(fielDir, 'private_key.key.tag')); // Read and decrypt metadata const metaEnc = await readFile(join(fielDir, 'metadata.json.enc')); const metaIv = await readFile(join(fielDir, 'metadata.json.iv')); const metaTag = await readFile(join(fielDir, 'metadata.json.tag')); // Decrypt all const cerData = decryptBuffer(cerEnc, cerIv, cerTag); const keyData = decryptBuffer(keyEnc, keyIv, keyTag); const metadata = JSON.parse(decryptBuffer(metaEnc, metaIv, metaTag).toString('utf-8')); // Write decrypted files await mkdir(outputDir, { recursive: true, mode: 0o700 }); await writeFile(join(outputDir, 'certificate.cer'), cerData, { mode: 0o600 }); await writeFile(join(outputDir, 'private_key.key'), keyData, { mode: 0o600 }); await writeFile(join(outputDir, 'metadata.json'), JSON.stringify(metadata, null, 2), { mode: 0o600 }); console.log(`\nDecrypted files written to: ${outputDir}`); console.log('Metadata:', metadata); console.log('\nFiles will be auto-deleted in 30 minutes.'); // Auto-delete after 30 minutes setTimeout(async () => { await rm(outputDir, { recursive: true, force: true }); console.log(`Cleaned up ${outputDir}`); process.exit(0); }, 30 * 60 * 1000); } main().catch((err) => { console.error('Failed to decrypt FIEL:', err.message); process.exit(1); });