import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto'; function encryptionKey() { const masterKey = process.env.HTTP_API_MASTER_KEY; if (!masterKey || masterKey.length < 32) { throw new Error('HTTP_API_MASTER_KEY must be configured with at least 32 characters'); } return createHash('sha256').update(masterKey).digest(); } export function encryptSecret(value: string) { const iv = randomBytes(12); const cipher = createCipheriv('aes-256-gcm', encryptionKey(), iv); const ciphertext = Buffer.concat([cipher.update(value, 'utf8'), cipher.final()]); return `${iv.toString('base64url')}.${cipher.getAuthTag().toString('base64url')}.${ciphertext.toString('base64url')}`; } export function decryptSecret(value: string) { const [iv, tag, ciphertext] = value.split('.'); if (!iv || !tag || !ciphertext) throw new Error('Invalid encrypted secret'); const decipher = createDecipheriv('aes-256-gcm', encryptionKey(), Buffer.from(iv, 'base64url')); decipher.setAuthTag(Buffer.from(tag, 'base64url')); return Buffer.concat([decipher.update(Buffer.from(ciphertext, 'base64url')), decipher.final()]).toString('utf8'); }