2 * Encryption utility for sensitive data
3 * Uses AES-256-GCM for encryption
6const crypto = require('crypto');
8const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY || process.env.JWT_SECRET;
9const ALGORITHM = 'aes-256-gcm';
12 throw new Error('ENCRYPTION_KEY or JWT_SECRET environment variable is required');
15// Derive a 32-byte key from the encryption key using scrypt
16// This works with keys of any length
17const KEY = crypto.scryptSync(ENCRYPTION_KEY, 'salt', 32);
20 * Encrypt a string value
21 * @param {string} text - Plain text to encrypt
22 * @returns {string} - Base64-encoded encrypted data with IV and auth tag
24function encrypt(text) {
25 if (!text) return null;
27 const iv = crypto.randomBytes(16);
28 const cipher = crypto.createCipheriv(ALGORITHM, KEY, iv);
30 let encrypted = cipher.update(text, 'utf8', 'hex');
31 encrypted += cipher.final('hex');
33 const authTag = cipher.getAuthTag();
35 // Format: iv:authTag:encryptedData
38 iv: iv.toString('hex'),
39 authTag: authTag.toString('hex'),
46 * Decrypt an encrypted string
47 * @param {string} encryptedData - Base64-encoded encrypted data
48 * @returns {string} - Decrypted plain text
50function decrypt(encryptedData) {
51 if (!encryptedData) return null;
54 const parsed = JSON.parse(
55 Buffer.from(encryptedData, 'base64').toString('utf8')
58 const iv = Buffer.from(parsed.iv, 'hex');
59 const authTag = Buffer.from(parsed.authTag, 'hex');
61 const decipher = crypto.createDecipheriv(ALGORITHM, KEY, iv);
62 decipher.setAuthTag(authTag);
64 let decrypted = decipher.update(parsed.data, 'hex', 'utf8');
65 decrypted += decipher.final('utf8');
69 console.error('Decryption failed:', error.message);