Jelajahi Sumber

mysql용 AES 암/복호화 내장함수에 따른 수정

gagamel 4 tahun lalu
induk
melakukan
9c210d7291

+ 83 - 8
src/main/java/com/style24/core/support/util/CryptoUtils.java

@@ -1,13 +1,17 @@
 package com.style24.core.support.util;
 
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.codec.binary.Base64;
-import org.apache.commons.lang3.StringUtils;
+import java.io.UnsupportedEncodingException;
 
 import javax.crypto.Cipher;
 import javax.crypto.spec.IvParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
 
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang3.StringUtils;
+
+import lombok.extern.slf4j.Slf4j;
+
 /**
  * 암호화 Util Class
  * @author gagamel
@@ -21,11 +25,11 @@ public class CryptoUtils {
 	private static final byte[] IV_BYTES = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
 	/**
-	 * AES 암호화 처리
+	 * YES24용 AES 암호화 처리
 	 * @param rawValue - 원시문자열
 	 * @return String - 암호화문자열
 	 */
-	public static String encryptAES(String rawValue) {
+	public static String encryptYes24AES(String rawValue) {
 		String encryptedValue = "";
 
 		try {
@@ -45,11 +49,11 @@ public class CryptoUtils {
 	}
 
 	/**
-	 * AES 복호화 처리
+	 * YES24 연동용 AES 복호화 처리
 	 * @param encryptedValue - 암호화된 문자열
 	 * @return String - 복호화문자열
 	 */
-	public static String decryptAES(String encryptedValue) {
+	public static String decryptYes24AES(String encryptedValue) {
 		String decryptedValue = "";
 
 		try {
@@ -59,7 +63,7 @@ public class CryptoUtils {
 				Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
 				cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(IV_BYTES));
 				decryptedValue = new String(cipher.doFinal(Base64.decodeBase64(encryptedValue.getBytes("UTF-8"))), "UTF-8");
-				if(StringUtils.isBlank(decryptedValue)) {
+				if (StringUtils.isBlank(decryptedValue)) {
 					decryptedValue = encryptedValue;
 				}
 			}
@@ -71,4 +75,75 @@ public class CryptoUtils {
 		return decryptedValue;
 	}
 
+	/**
+	 * JAVA에서는 AES키는 16byte이지만, MySQL에서는 16byte 이상도 지원하기에 MySQL의 16byte 이상의 키를 생성해야 한다.
+	 * 16byte 이상은 잘라서 다시 앞쪽부터 byte 단위로 XOR 시켜서 16byte 키로 생성
+	 * @param encoding
+	 * @return
+	 */
+	private static SecretKeySpec generateMysqlAESKey(final String encoding) {
+		try {
+			final byte[] finalKey = new byte[16];
+			int i = 0;
+			for (byte b : AES_KEY.getBytes(encoding)) {
+				finalKey[i++ % 16] ^= b;
+			}
+			return new SecretKeySpec(finalKey, "AES");
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException(e);
+		}
+	}
+
+	/**
+	 * MySQL AES128 암호화 처리
+	 * 		MySQL) HEX(AES_ENCRYPT('테스트', AES_KEY))
+	 * @param rawValue - 원시문자열
+	 * @return String - 암호화문자열
+	 */
+	public static String encryptAES(String rawValue) {
+		String encryptedValue = "";
+
+		try {
+			final Cipher cipher = Cipher.getInstance("AES"); // Cipher.getInstance("AES/ECB/PKCS5Padding")와 같음. ECB 모드의 경우 cipher.init 시 IvParameterSpec을 넣음 안 된다.
+			cipher.init(Cipher.ENCRYPT_MODE, generateMysqlAESKey("UTF-8"));
+			encryptedValue = new String(Hex.encodeHex(cipher.doFinal(rawValue.getBytes("UTF-8")))).toUpperCase();
+		} catch (Exception e) {
+//			log.error(e.getMessage());
+			encryptedValue = rawValue;
+		}
+
+		return encryptedValue;
+	}
+
+	/**
+	 * MySQL AES128 복호화 처리
+	 * 		MySQL) CAST(AES_DECRYPT(UNHEX('0EF41E8ED0A5D40D2F8DC4C0A3A9C722'),AES_KEY) AS CHAR)
+	 * @param encryptedValue - 암호화된 문자열
+	 * @return String - 복호화문자열
+	 */
+	public static String decryptAES(String encryptedValue) {
+		String decryptedValue = "";
+
+		try {
+			final Cipher cipher = Cipher.getInstance("AES"); // Cipher.getInstance("AES/ECB/PKCS5Padding")와 같음 
+			cipher.init(Cipher.DECRYPT_MODE, generateMysqlAESKey("UTF-8"));
+			decryptedValue = new String(cipher.doFinal(Hex.decodeHex(encryptedValue.toCharArray())));
+		} catch (Exception e) {
+//			log.error(e.getMessage());
+			decryptedValue = encryptedValue;
+		}
+
+		return decryptedValue;
+	}
+
+//	public static void main(String[] args) throws Exception {
+//		String txt = "테스트";
+//		String encrypt = CryptoUtils.encryptAES(txt);
+//		String decrypt = CryptoUtils.decryptAES(encrypt);
+//
+//		log.info("평문 : {}", txt);
+//		log.info("암호화 : {}", encrypt);
+//		log.info("복호화 : {}", decrypt);
+//	}
+
 }