diff --git a/ext-libs/safedb/README.md b/ext-libs/safedb/README.md deleted file mode 100644 index d1dd670..0000000 --- a/ext-libs/safedb/README.md +++ /dev/null @@ -1,2 +0,0 @@ -SafeDBSDK_v4.0.19.jar 파일은 빌드결과에 포함되지 않고 compileOnly 로만 사용 -실제 라이브러리는 WAS classpath 로 지정 \ No newline at end of file diff --git a/ext-libs/safedb/SafeDBSDK_v4.0.19.jar b/ext-libs/safedb/SafeDBSDK_v4.0.19.jar deleted file mode 100644 index bb50136..0000000 Binary files a/ext-libs/safedb/SafeDBSDK_v4.0.19.jar and /dev/null differ diff --git a/src/main/java/com/eactive/ext/kjb/safedb/SafeDBFaker.java b/src/main/java/com/eactive/ext/kjb/safedb/SafeDBFaker.java deleted file mode 100644 index bc9b733..0000000 --- a/src/main/java/com/eactive/ext/kjb/safedb/SafeDBFaker.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.eactive.ext.kjb.safedb; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.util.Base64Utils; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.Base64; - -/** - * SafeDBFaker provides a fake encryption method for testing purposes when the real SafeDB library is not available. - */ -@Slf4j -public abstract class SafeDBFaker { - private static final String AES_256_KEY = "1234567890123456" + "1234567890123456"; - private static final byte[] IV = "1234567890123456".getBytes(); - - - public byte[] encrypt(String userId, String table, String column, byte[] data) { - if (SafeDBColumns.PSWD.isEqualsIgnoreCase(column)) { - // SHA256 + Base64 인코딩된 가짜 비밀번호 반환 - return sha256(data); - } else { - // AES256 암호화된 가짜 데이터 반환 - return aes256Encrypt(data); - } - } - - public byte[] decrypt(String userId, String table, String column, byte[] data) { - if (SafeDBColumns.PSWD.isEqualsIgnoreCase(column)) { - // 비밀번호는 복호화하지 않음 - throw new UnsupportedOperationException("Password decryption is not supported."); - } else { - // AES256 복호화된 가짜 데이터 반환 - return aes256Decrypt(data); - } - } - - private byte[] sha256(byte[] data) { - MessageDigest digest = null; - try { - digest = MessageDigest.getInstance("SHA-256"); - return digest.digest(data); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException("Error generating SHA-256 hash", e); - } - } - - private String sha256Base64(String data) { - return Base64.getEncoder().encodeToString(this.sha256(data.getBytes())); - } - - // AES256 암호화 - private byte[] aes256Encrypt(byte[] data) { - try { - Cipher cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding"); - SecretKeySpec keySpec = new javax.crypto.spec.SecretKeySpec(AES_256_KEY.getBytes(), "AES"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(IV)); - return cipher.doFinal(data); - } catch (Exception e) { - throw new RuntimeException("Error during AES encryption", e); - } - } - - private String getAes256KeyString(String data) { - return Base64.getEncoder().encodeToString(this.aes256Encrypt(data.getBytes())); - } - - private byte[] aes256Decrypt(byte[] encryptedData) { - try { - Cipher cipher = javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding"); - SecretKeySpec keySpec = new javax.crypto.spec.SecretKeySpec(AES_256_KEY.getBytes(), "AES"); - cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(IV)); - log.debug("encryptedData : {}", Arrays.toString(encryptedData)); - log.debug("encryptedData toString() : {}", new String(encryptedData)); - return cipher.doFinal(encryptedData); - } catch (Exception e) { - throw new RuntimeException("Error during AES decryption", e); - } - } - - public String encryptString(String userId, String table, String column, String data) { -// return new String(this.encrypt(safedb, s, notRnno, data.getBytes())); - return Base64Utils.encodeToString(this.encrypt(userId, table, column, data.getBytes())); - } - - protected String decryptString(String userId, String table, String column, String data) { - return new String(this.decrypt(userId, table, column, Base64Utils.decodeFromString(data))); - } -} diff --git a/src/main/java/com/eactive/ext/kjb/safedb/SafeDBWrapper.java b/src/main/java/com/eactive/ext/kjb/safedb/SafeDBWrapper.java deleted file mode 100644 index e67d4fb..0000000 --- a/src/main/java/com/eactive/ext/kjb/safedb/SafeDBWrapper.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.eactive.ext.kjb.safedb; - -import com.initech.safedb.SimpleSafeDB; -import lombok.Getter; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.repository.init.ResourceReader; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; - -@Slf4j -public class SafeDBWrapper extends SafeDBBroker { - private static SafeDBWrapper instance; - - private SimpleSafeDB safedb; - @Getter - private boolean isRealSafeDB = false; - - - public static SafeDBWrapper getInstance() { - if ( instance == null ) { - synchronized ( SafeDBWrapper.class ) { - if ( instance == null ) { - instance = new SafeDBWrapper(); - } - } - } - return instance; - } - - public static boolean isBase64(String str) { - if (str == null || str.isEmpty()) { - return false; - } - String base64Pattern = "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"; - return str.matches(base64Pattern); - } - - - private SafeDBWrapper() throws SafeDBWrapperException { - synchronized ( SafeDBWrapper.class ) { - // "com.initech.safedb.SimpleSafeDB" 클래스 존재 여부 확인 - try { - Class.forName("com.initech.safedb.SimpleSafeDB"); - - try (InputStream is = ResourceReader.class.getClassLoader().getResourceAsStream("SafeDBMap_config.xml")) { - if (is == null) { - isRealSafeDB = false; - return; - } else { - try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) { - br.lines().forEach(log::debug); - } - } - - } - - this.safedb = SimpleSafeDB.getInstance(); - - if (safedb.login()) { - log.debug("[SafeDBWrapper] isLoginCheck : {}", safedb.getSafeDBConfigMgr().isLoginCheck()); - } else { - log.warn("[SafeDBWrapper] isLoginCheck : {}", safedb.getSafeDBConfigMgr().isLoginCheck()); - } - - isRealSafeDB = true; // 클래스가 존재하면 true로 설정 - } catch (Exception e) { - isRealSafeDB = false; // 클래스가 존재하지 않으면 false로 설정 - log.info("SafeDB 클래스 로딩 실패 - 로컬 환경이거나 설정 오류 / Fake 모드로 동작함", e); - } - - if (isRealSafeDB) { - try { - super.initialize(); - } catch (Exception e) { - throw new SafeDBWrapperException("[SafeDBWrapper] Initialization error: " + e.getMessage(), e); - } - } - } - } - - @Override - public byte[] encrypt(String userId, String table, String column, byte[] data) throws SafeDBWrapperSdkException { - if (isRealSafeDB) { - try { - log.debug("[SafeDBWrapper] real / userId : {}, table : {}, column : {}, data : {}", userId, table, column, data); - return safedb.encrypt(userId, table, column, data); - } catch (Exception e) { - throw new SafeDBWrapperSdkException("[SafeDBWrapper] Encrypt error: " + e.getMessage(), e); - } - } else { - return super.encrypt(userId, table, column, data); - } - } - - @Override - public String encryptString(String userId, String tables, String column, String data) { - if (isRealSafeDB) { - try { - return this.safedb.encryptString(userId, tables, column, data); - } catch (Exception e) { - throw new SafeDBWrapperSdkException("[SafeDBWrapper] Encrypt error: " + e.getMessage(), e); - } - } else { - return super.encryptString(userId, tables, column, data); - } - } - - public String encryptNotRnnoString(String data) throws SafeDBWrapperSdkException { - return this.encryptString("SAFEDB", "SAFEDB.POLICY", "NOT_RNNO", data); - } - - @Override - public byte[] decrypt(String userId, String table, String column, byte[] data) throws SafeDBWrapperSdkException { - if (isRealSafeDB) { - try { - return safedb.decrypt(userId, table, column, data); - } catch (Exception e) { - throw new SafeDBWrapperException("[SafeDBWrapper] Decrypt error: " + e.getMessage(), e); - } - } else { - return super.decrypt(userId, table, column, data); - } - } - - public String decryptString(String userId, String table, String column, String data) throws SafeDBWrapperSdkException { - if (isRealSafeDB) { - try { - return safedb.decryptString(userId, table, column, data); - } catch (Exception e) { - throw new SafeDBWrapperException("[SafeDBWrapper] Decrypt error: " + e.getMessage(), e); - } - } else { - return super.decryptString(userId, table, column, data); - } - } - - public String decryptNotRnno(String data) throws SafeDBWrapperSdkException { - return this.decryptString("SAFEDB", "SAFEDB.POLICY", "NOT_RNNO", data); - } -} diff --git a/src/test/java/com/eactive/ext/kjb/safedb/test/SafeDbWrapperTest.java b/src/test/java/com/eactive/ext/kjb/safedb/test/SafeDbWrapperTest.java deleted file mode 100644 index 863cba5..0000000 --- a/src/test/java/com/eactive/ext/kjb/safedb/test/SafeDbWrapperTest.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.eactive.ext.kjb.safedb.test; - -import com.eactive.ext.kjb.safedb.SafeDBWrapper; -import lombok.extern.slf4j.Slf4j; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -@Slf4j -public class SafeDbWrapperTest { - - @Test - public void fakeSafeDBTest() { - log.info("FakeSafeDBWrapper Length Validation Start"); - - if ("true".equalsIgnoreCase(System.getenv("safedb"))) { - log.info("실제 Safedb 테스트를 위해 테스트 종료 처리"); - assertTrue("true".equalsIgnoreCase(System.getenv("safedb"))); - return; - } - - SafeDBWrapper wrapper; - try { - wrapper = SafeDBWrapper.getInstance(); - } catch (Exception e) { - // classloader 에러인지 initialization 에러인지 구분 - if (e.getMessage().contains("Classloader error")) { - throw new RuntimeException("SafeDBWrapper classloader error: " + e.getMessage(), e); - } else { - // initialization 에러(로컬에서는 동작하지 않는다 = 정상 처리) - log.info("SafeDBWrapper initialization error (expected in local environment): " + e.getMessage()); - return; - } - } - - if (wrapper.isRealSafeDB()) { - log.info("This test is for FakeSafeDBWrapper only. Skipping test."); - return; - } - - - for (int len = 1; len <= 255; len++) { - String originalData = repeat("A", len); // JDK8 호환 반복 문자열 - try { - log.debug("OriginalData: {}", originalData); - - // 암호화 (Base64 인코딩 결과 가정) - String encryptedData = wrapper.encryptNotRnnoString(originalData); - log.debug("Encrypted Data: {}", encryptedData); - - // 예상 암호문 길이 계산 - int expectedLen = getExpectedCipherLength(len, true); - - // 복호화 - String decryptedData = wrapper.decryptNotRnno(encryptedData); - log.debug("Decrypted Data: {}", decryptedData); - assertEquals(originalData, decryptedData, "Decrypted data does not match original at plain length=" + len); - - // 로그 출력 - log.info(String.format("Plain=%3d, Encrypted=%3d, Expected=%3d %s", - len, encryptedData.length(), expectedLen, - (encryptedData.length() == expectedLen ? "✔" : "❌"))); - - // 검증 - // "Length mismatch at plain length=" - assertEquals(len, expectedLen, encryptedData.length()); - - - // 암복호화 로그 출력 - log.info(String.format("Original: %s", originalData) + - String.format("\nEncrypted: %s", encryptedData) + - String.format("\nDecrypted: %s", decryptedData) + "\n"); - - - } catch (Exception e) { - throw new RuntimeException("Error at plain length=" + len, e); - } - } - } - - @SuppressWarnings("CallToPrintStackTrace") - @Test - public void safeDBTest() { - // safedb 프러퍼티가 활성화 일때만 동작 - if (!"true".equalsIgnoreCase(System.getProperty("safedb"))) { - log.info("gradle : -Psafedb 일때만 동작 - {}", System.getProperty("safedb")); - return; - } - - SafeDBWrapper wrapper; - try { - wrapper = SafeDBWrapper.getInstance(); - } catch (Exception e) { - log.error("SafeDBWrapper 활성화 실패"); - fail(); - return; - } - - if (!wrapper.isRealSafeDB()) { - log.error("실제 Safedb 로 동작하지 않음"); - fail(); - return; - } - - String value = "한글암호화테스트"; - log.info("Original : {}", value); - - try { - String encryptValue = wrapper.encryptNotRnnoString(value); - log.info("Encrypted : {}", encryptValue); - - String decryptedValue = wrapper.decryptNotRnno(encryptValue); - log.info("Decrypted : {}", decryptedValue); - - assertEquals(value, decryptedValue); - } catch (Exception e) { - e.printStackTrace(); - fail(); - return; - } - - - - assertTrue(true); - } - /** - * 암호문 예상 길이 계산 (AES/SEED/ARIA CBC 기준, PKCS5Padding) - */ - @SuppressWarnings("SameParameterValue") - private int getExpectedCipherLength(int plainLength, boolean base64Encoding) { - int blockSize = 16; - int paddedLength = ((plainLength / blockSize) + 1) * blockSize; - - if (base64Encoding) { - return (int) (Math.ceil(paddedLength / 3.0) * 4); - } else { - return paddedLength; - } - } - - /** JDK8에서 문자열 반복 (String.repeat 대체) */ - @SuppressWarnings("SameParameterValue") - private String repeat(String s, int count) { - StringBuilder sb = new StringBuilder(s.length() * count); - for (int i = 0; i < count; i++) { - sb.append(s); - } - return sb.toString(); - } -}