File size: 1,941 Bytes
ad573c0 8dde1b0 ad573c0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | import crypto from 'crypto';
import fs from 'fs/promises';
import path from 'path';
const ALGORITHM = 'aes-256-gcm';
const KEY_LENGTH = 32; // 256 bits
const IV_LENGTH = 16; // 128 bits for GCM
const AUTH_TAG_LENGTH = 16; // 128 bits
// Derive key from environment variable
function getKey() {
const keyEnv = process.env.DATA_ENCRYPTION_KEY;
if (!keyEnv) throw new Error('DATA_ENCRYPTION_KEY environment variable not set');
// Use SHA-256 to derive a 32-byte key from the env var
return crypto.createHash('sha256').update(keyEnv).digest();
}
export function encryptJson(data) {
const key = getKey();
const iv = crypto.randomBytes(IV_LENGTH);
const cipher = crypto.createCipher(ALGORITHM, key);
cipher.setAAD(Buffer.from('')); // Optional AAD
let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'hex');
encrypted += cipher.final('hex');
const authTag = cipher.getAuthTag();
return {
iv: iv.toString('hex'),
encrypted,
authTag: authTag.toString('hex'),
};
}
export function decryptJson(encryptedData) {
const key = getKey();
const { iv, encrypted, authTag } = encryptedData;
const decipher = crypto.createDecipher(ALGORITHM, key);
decipher.setAuthTag(Buffer.from(authTag, 'hex'));
decipher.setAAD(Buffer.from('')); // Match AAD
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return JSON.parse(decrypted);
}
export async function saveEncryptedJson(filePath, data) {
const encrypted = encryptJson(data);
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(filePath, JSON.stringify(encrypted));
}
export async function loadEncryptedJson(filePath) {
try {
const content = await fs.readFile(filePath, 'utf8');
const encrypted = JSON.parse(content);
return decryptJson(encrypted);
} catch (err) {
if (err.code === 'ENOENT') return null; // File not found
throw err;
}
} |