import crypto from "node:crypto"; const APP_KEY_MATERIAL = "MDD-v2-backup-aes256gcm-2026"; const ALGORITHM = "aes-256-gcm"; const IV_LENGTH = 12; const AUTH_TAG_LENGTH = 16; const MAGIC = Buffer.from("MDD1"); function deriveKey(): Buffer { return crypto.createHash("sha256").update(APP_KEY_MATERIAL).digest(); } export function encryptBackup(plaintext: string): Buffer { const key = deriveKey(); const iv = crypto.randomBytes(IV_LENGTH); const cipher = crypto.createCipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH }); const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]); const authTag = cipher.getAuthTag(); return Buffer.concat([MAGIC, iv, authTag, encrypted]); } export function decryptBackup(data: Buffer): string { if (data.length < MAGIC.length + IV_LENGTH + AUTH_TAG_LENGTH) { throw new Error("Backup-Datei zu kurz oder ungültig"); } const magic = data.subarray(0, MAGIC.length); if (!magic.equals(MAGIC)) { throw new Error("Keine gültige MDD-Backup-Datei (falsche Signatur)"); } const iv = data.subarray(MAGIC.length, MAGIC.length + IV_LENGTH); const authTag = data.subarray(MAGIC.length + IV_LENGTH, MAGIC.length + IV_LENGTH + AUTH_TAG_LENGTH); const ciphertext = data.subarray(MAGIC.length + IV_LENGTH + AUTH_TAG_LENGTH); const key = deriveKey(); const decipher = crypto.createDecipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH }); decipher.setAuthTag(authTag); const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]); return decrypted.toString("utf8"); }