import { CHALLENGE_SECRET } from '$env/static/private'; import * as crypto from 'crypto'; import { v4 } from 'uuid'; const IV_LENGTH = 16; const ALGORITHM = 'aes-256-cbc'; export class CryptoUtils { public static generateString(length: number): string { return crypto.randomBytes(length).toString('hex').slice(0, length); } public static generateSecret(): string { return crypto.randomBytes(256 / 8).toString('hex'); } public static insecureHash(input: string): string { return crypto.createHash('md5').update(input).digest('hex'); } public static createUUID(): string { return v4(); } // https://stackoverflow.com/q/52212430 /** * Symmetric encryption function * @param text String to encrypt * @param key Encryption key * @returns Encrypted text */ public static encrypt(text: string, key: string): string { const iv = crypto.randomBytes(IV_LENGTH); const cipher = crypto.createCipheriv(ALGORITHM, Buffer.from(key, 'hex'), iv); let encrypted = cipher.update(text); encrypted = Buffer.concat([encrypted, cipher.final()]); return `${iv.toString('hex')}:${encrypted.toString('hex')}`; } /** * Symmetric decryption function * @param text Encrypted string * @param key Decryption key * @returns Decrypted text */ public static decrypt(text: string, key: string): string { const [iv, encryptedText] = text.split(':').map((part) => Buffer.from(part, 'hex')); const decipher = crypto.createDecipheriv(ALGORITHM, Buffer.from(key, 'hex'), iv); let decrypted = decipher.update(encryptedText); decrypted = Buffer.concat([decrypted, decipher.final()]); return decrypted.toString(); } public static async encryptChallenge(challenge: T): Promise { return this.encrypt(JSON.stringify(challenge), CHALLENGE_SECRET); } public static async decryptChallenge(challenge: string): Promise { return JSON.parse(this.decrypt(challenge, CHALLENGE_SECRET)); } }