import crypto from "crypto"; import { env } from "@/config/env.js"; const ALGORITHM = "aes-256-gcm"; const IV_LENGTH = 16; const AUTH_TAG_LENGTH = 16; export function encrypt(text: string): string { const iv = crypto.randomBytes(IV_LENGTH); const key = Buffer.from(env.ENCRYPTION_KEY.slice(0, 32), "utf-8"); const cipher = crypto.createCipheriv(ALGORITHM, key, iv); let encrypted = cipher.update(text, "utf8", "hex"); encrypted += cipher.final("hex"); const authTag = cipher.getAuthTag(); return `${iv.toString("hex")}:${authTag.toString("hex")}:${encrypted}`; } export function decrypt(encryptedText: string): string { const parts = encryptedText.split(":"); if (parts.length !== 3) { throw new Error("Invalid encrypted text format"); } const iv = Buffer.from(parts[0], "hex"); const authTag = Buffer.from(parts[1], "hex"); const encrypted = parts[2]; const key = Buffer.from(env.ENCRYPTION_KEY.slice(0, 32), "utf-8"); const decipher = crypto.createDecipheriv(ALGORITHM, key, iv); decipher.setAuthTag(authTag); let decrypted = decipher.update(encrypted, "hex", "utf8"); decrypted += decipher.final("utf8"); return decrypted; } export function hashApiKey(key: string): string { return crypto.createHash("sha256").update(key).digest("hex"); } export function generateWebhookSignature(payload: string, secret: string): string { return `sha256=${crypto.createHmac("sha256", secret).update(payload).digest("hex")}`; } export function verifyWebhookSignature( payload: string, signature: string, secret: string ): boolean { const expected = generateWebhookSignature(payload, secret); return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); }