papjackrock / src /utils /crypto.ts
kylsprt's picture
Nice-time
6368531 verified
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));
}