import crypto from "crypto"; /** * 자격 증명 암호화 유틸리티 * AES-256-GCM 알고리즘 사용 */ export class CredentialEncryption { private algorithm = "aes-256-gcm"; private key: Buffer; constructor(secretKey: string) { // scrypt로 안전한 키 생성 this.key = crypto.scryptSync(secretKey, "salt", 32); } /** * 평문을 암호화 */ encrypt(text: string): string { const iv = crypto.randomBytes(16); const cipher = crypto.createCipheriv( this.algorithm, this.key, iv ) as crypto.CipherGCM; let encrypted = cipher.update(text, "utf8", "hex"); encrypted += cipher.final("hex"); const authTag = cipher.getAuthTag(); // IV:AuthTag:EncryptedText 형식으로 반환 return `${iv.toString("hex")}:${authTag.toString("hex")}:${encrypted}`; } /** * 암호문을 복호화 */ decrypt(encrypted: string): string { const [ivHex, authTagHex, encryptedText] = encrypted.split(":"); if (!ivHex || !authTagHex || !encryptedText) { throw new Error("Invalid encrypted string format"); } const iv = Buffer.from(ivHex, "hex"); const authTag = Buffer.from(authTagHex, "hex"); const decipher = crypto.createDecipheriv( this.algorithm, this.key, iv ) as crypto.DecipherGCM; decipher.setAuthTag(authTag); let decrypted = decipher.update(encryptedText, "hex", "utf8"); decrypted += decipher.final("utf8"); return decrypted; } }