// 기존 Java EncryptUtil 클래스를 Node.js로 포팅 // AES/ECB/NoPadding 암호화 방식 사용 import crypto from "crypto"; // 기존 Java Constants에서 가져온 값들 const KEY_NAME = "ILJIAESSECRETKEY"; const ALGORITHM = "AES"; const MASTER_PWD = "qlalfqjsgh11"; export class PasswordUtils { /** * 기존 Java EncryptUtil.encrypt() 메서드 포팅 * AES/ECB/NoPadding 방식으로 암호화 */ static encrypt(source: string): string { try { // 16바이트 키 생성 (AES-128) const key = Buffer.from(KEY_NAME, "utf8").slice(0, 16); // 패딩 추가 (16바이트 블록 크기에 맞춤) const paddedData = this.addPadding(Buffer.from(source, "utf8")); // AES 암호화 const cipher = crypto.createCipher("aes-128-ecb", key); cipher.setAutoPadding(false); // NoPadding 모드 let encrypted = cipher.update(paddedData); encrypted = Buffer.concat([encrypted, cipher.final()]); // 16진수 문자열로 변환 return this.fromHex(encrypted); } catch (error) { console.error("Password encryption error:", error); throw new Error("암호화 중 오류가 발생했습니다."); } } /** * 기존 Java EncryptUtil.decrypt() 메서드 포팅 */ static decrypt(source: string): string { try { // 16바이트 키 생성 const key = Buffer.from(KEY_NAME, "utf8").slice(0, 16); // 16진수 문자열을 바이트 배열로 변환 const encryptedData = this.toBytes(source); // AES 복호화 const decipher = crypto.createDecipher("aes-128-ecb", key); decipher.setAutoPadding(false); // NoPadding 모드 let decrypted = decipher.update(encryptedData); decrypted = Buffer.concat([decrypted, decipher.final()]); // 패딩 제거 const unpaddedData = this.removePadding(decrypted); return unpaddedData.toString("utf8"); } catch (error) { console.error("Password decryption error:", error); throw new Error("복호화 중 오류가 발생했습니다."); } } /** * 기존 Java EncryptUtil.encryptSha256() 메서드 포팅 */ static encryptSha256(s: string): string { try { const hash = crypto.createHash("sha256"); hash.update(s, "utf8"); return hash.digest("hex"); } catch (error) { console.error("SHA256 encryption error:", error); return ""; } } /** * 비밀번호 검증 (기존 Java 로직과 동일) */ static matches(plainPassword: string, encryptedPassword: string): boolean { try { // 마스터 패스워드 체크 if (MASTER_PWD === plainPassword) { return true; } // 일반 패스워드 암호화 후 비교 const encryptedPlainPassword = this.encrypt(plainPassword); return encryptedPlainPassword === encryptedPassword; } catch (error) { console.error("Password matching error:", error); return false; } } /** * 기존 Java addPadding() 메서드 포팅 * 16바이트 블록 크기에 맞춰 패딩 추가 */ private static addPadding(pBytes: Buffer): Buffer { const pCount = pBytes.length; const tCount = pCount + (16 - (pCount % 16)); const tBytes = Buffer.alloc(tCount); pBytes.copy(tBytes, 0); // 나머지 바이트를 0x00으로 채움 for (let rIndex = pCount; rIndex < tCount; rIndex++) { tBytes[rIndex] = 0x00; } return tBytes; } /** * 기존 Java removePadding() 메서드 포팅 * 패딩 제거 */ private static removePadding(pBytes: Buffer): Buffer { const pCount = pBytes.length; let index = 0; let loop = true; while (loop) { if (index === pCount || pBytes[index] === 0x00) { loop = false; index--; } index++; } const tBytes = Buffer.alloc(index); pBytes.copy(tBytes, 0, 0, index); return tBytes; } /** * 기존 Java toBytes() 메서드 포팅 * 16진수 문자열을 바이트 배열로 변환 */ private static toBytes(pSource: string): Buffer { const buff = pSource; const bCount = Math.floor(buff.length / 2); const bArr = Buffer.alloc(bCount); for (let bIndex = 0; bIndex < bCount; bIndex++) { const hexByte = buff.substring(2 * bIndex, 2 * bIndex + 2); bArr[bIndex] = parseInt(hexByte, 16); } return bArr; } /** * 기존 Java fromHex() 메서드 포팅 * 바이트 배열을 16진수 문자열로 변환 */ private static fromHex(pBytes: Buffer): string { const pCount = pBytes.length; let buff = ""; for (let pIndex = 0; pIndex < pCount; pIndex++) { const byte = pBytes[pIndex] & 0xff; if (byte < 0x10) { buff += "0"; } buff += byte.toString(16); } return buff; } /** * 테스트용 메서드 (개발 환경에서만 사용) */ static testEncryption(plainText: string): void { console.log("=== 암호화 테스트 ==="); console.log("원본 텍스트:", plainText); const encrypted = this.encrypt(plainText); console.log("암호화 결과:", encrypted); const decrypted = this.decrypt(encrypted); console.log("복호화 결과:", decrypted); const isMatch = this.matches(plainText, encrypted); console.log("비밀번호 일치:", isMatch); const sha256Hash = this.encryptSha256(plainText); console.log("SHA256 해시:", sha256Hash); } }