feat: AES-256-GCM 암호화 적용 (tel, email), 로그/배포 설정 추가
This commit is contained in:
78
src/main/java/com/owrawww/util/AesUtil.java
Normal file
78
src/main/java/com/owrawww/util/AesUtil.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package com.owrawww.util;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* AES-256-GCM 암호화/복호화 유틸리티
|
||||
* - IV(12 bytes) + 암호문을 Base64로 인코딩하여 저장
|
||||
*/
|
||||
@Component
|
||||
public class AesUtil {
|
||||
|
||||
private static final String ALGORITHM = "AES/GCM/NoPadding";
|
||||
private static final int IV_LENGTH = 12; // GCM 권장 IV 크기
|
||||
private static final int TAG_BIT_LEN = 128; // GCM 인증 태그 크기
|
||||
|
||||
private final SecretKey secretKey;
|
||||
|
||||
public AesUtil(@Value("${app.encryption.key}") String base64Key) {
|
||||
byte[] keyBytes = Base64.getDecoder().decode(base64Key);
|
||||
if (keyBytes.length != 32) {
|
||||
throw new IllegalArgumentException("암호화 키는 Base64 인코딩된 32바이트(256bit)여야 합니다.");
|
||||
}
|
||||
this.secretKey = new SecretKeySpec(keyBytes, "AES");
|
||||
}
|
||||
|
||||
/**
|
||||
* 평문 → AES-256-GCM 암호화 → Base64 문자열
|
||||
*/
|
||||
public String encrypt(String plainText) {
|
||||
if (plainText == null || plainText.isEmpty()) return plainText;
|
||||
try {
|
||||
byte[] iv = new byte[IV_LENGTH];
|
||||
new SecureRandom().nextBytes(iv);
|
||||
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new GCMParameterSpec(TAG_BIT_LEN, iv));
|
||||
byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
|
||||
|
||||
// IV + 암호문 결합 후 Base64 인코딩
|
||||
byte[] combined = new byte[IV_LENGTH + encrypted.length];
|
||||
System.arraycopy(iv, 0, combined, 0, IV_LENGTH);
|
||||
System.arraycopy(encrypted, 0, combined, IV_LENGTH, encrypted.length);
|
||||
|
||||
return Base64.getEncoder().encodeToString(combined);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("암호화 실패", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Base64 암호문 → AES-256-GCM 복호화 → 평문
|
||||
*/
|
||||
public String decrypt(String encryptedText) {
|
||||
if (encryptedText == null || encryptedText.isEmpty()) return encryptedText;
|
||||
try {
|
||||
byte[] combined = Base64.getDecoder().decode(encryptedText);
|
||||
byte[] iv = new byte[IV_LENGTH];
|
||||
byte[] cipherText = new byte[combined.length - IV_LENGTH];
|
||||
|
||||
System.arraycopy(combined, 0, iv, 0, IV_LENGTH);
|
||||
System.arraycopy(combined, IV_LENGTH, cipherText, 0, cipherText.length);
|
||||
|
||||
Cipher cipher = Cipher.getInstance(ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKey, new GCMParameterSpec(TAG_BIT_LEN, iv));
|
||||
return new String(cipher.doFinal(cipherText), "UTF-8");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("복호화 실패", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user