import { createLogger } from '@sim/logger' import { decrypt, encrypt } from '@sim/security/encryption' import { toError } from '@sim/utils/errors' import { randomInt } from '@sim/utils/random' import { env } from '@/lib/core/config/env' const logger = createLogger('Encryption') function getEncryptionKey(): Buffer { const key = env.ENCRYPTION_KEY if (!key || key.length !== 64) { throw new Error('ENCRYPTION_KEY must be set to a 64-character hex string (32 bytes)') } return Buffer.from(key, 'hex') } /** * Encrypts a secret using AES-256-GCM with the app's `ENCRYPTION_KEY`. * @param secret - The secret to encrypt * @returns A promise resolving to the encrypted value (`iv:ciphertext:authTag`) and the IV. */ export async function encryptSecret(secret: string): Promise<{ encrypted: string; iv: string }> { return encrypt(secret, getEncryptionKey()) } /** * Decrypts a secret previously produced by {@link encryptSecret}. Logs and * rethrows on malformed input or tampered ciphertext. */ export async function decryptSecret(encryptedValue: string): Promise<{ decrypted: string }> { try { return await decrypt(encryptedValue, getEncryptionKey()) } catch (error) { logger.error('Decryption error:', { error: toError(error).message }) throw error } } /** * Generates a secure random password * @param length - The length of the password (default: 24) * @returns A new secure password string */ export function generatePassword(length = 24): string { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_-+=' let result = '' for (let i = 0; i < length; i++) { result += chars.charAt(randomInt(0, chars.length)) } return result }