import crypto from 'node:crypto' const ALGORITHM = 'chacha20-poly1305' const NONCE_LENGTH = 12 const TAG_LENGTH = 16 function getKey(): Buffer { const hex = process.env.ENCRYPTION_KEY if (!hex || hex.length !== 64) { throw new Error('ENCRYPTION_KEY must be a 64-character hex string (32 bytes)') } return Buffer.from(hex, 'hex') } export function encrypt(plaintext: string): string { const key = getKey() const nonce = crypto.randomBytes(NONCE_LENGTH) const cipher = crypto.createCipheriv(ALGORITHM, key, nonce, { authTagLength: TAG_LENGTH }) const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]) const tag = cipher.getAuthTag() return Buffer.concat([nonce, tag, encrypted]).toString('hex') } export function decrypt(ciphertext: string): string { const key = getKey() const buf = Buffer.from(ciphertext, 'hex') const nonce = buf.subarray(0, NONCE_LENGTH) const tag = buf.subarray(NONCE_LENGTH, NONCE_LENGTH + TAG_LENGTH) const encrypted = buf.subarray(NONCE_LENGTH + TAG_LENGTH) const decipher = crypto.createDecipheriv(ALGORITHM, key, nonce, { authTagLength: TAG_LENGTH }) decipher.setAuthTag(tag) return decipher.update(encrypted) + decipher.final('utf8') }