암복호화 함수 이름 변경 및 단위테스트 추가
- 클래스이름 오타 수정 - Parser 단위 테스트 추가
This commit is contained in:
+6
-6
@@ -13,17 +13,17 @@ import com.eactive.eai.common.security.CryptoModuleService;
|
||||
/**
|
||||
* JEP 트랜스포머 함수 — DJB ERP 연동 복호화.
|
||||
*
|
||||
* 사용법: DJBErpDecryt(encBase64, moduleName) DJBErpDecryt(encBase64, moduleName,
|
||||
* groupSeq)
|
||||
* 사용법: DJBErpDecryt(encBase64, moduleName)
|
||||
*
|
||||
* 파라미터: encBase64 : Base64 인코딩된 암호문 (String) moduleName : DB에 등록된 암호화 모듈명
|
||||
* (String) groupSeq : 키 도출용 그룹 시퀀스 (String, 선택). 미전달 시 빈 context로 호출.
|
||||
* 파라미터:
|
||||
* encBase64 : Base64 인코딩된 암호문
|
||||
* moduleName : DB에 등록된 암호화 모듈명
|
||||
*
|
||||
* 반환값: 복호화된 평문 (String)
|
||||
*/
|
||||
public class DJBDecryt extends PostfixMathCommand {
|
||||
public class DJBDecrypt extends PostfixMathCommand {
|
||||
|
||||
public DJBDecryt() {
|
||||
public DJBDecrypt() {
|
||||
numberOfParameters = -1;
|
||||
}
|
||||
|
||||
+2
-2
@@ -21,9 +21,9 @@ import com.eactive.eai.common.security.CryptoModuleService;
|
||||
*
|
||||
* 반환값: Base64 인코딩된 암호문 (String)
|
||||
*/
|
||||
public class DJBEncryt extends PostfixMathCommand {
|
||||
public class DJBEncrypt extends PostfixMathCommand {
|
||||
|
||||
public DJBEncryt() {
|
||||
public DJBEncrypt() {
|
||||
numberOfParameters = -1;
|
||||
}
|
||||
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
package com.eactive.eai.custom.transformer.function;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
import com.eactive.eai.common.security.CryptoModuleService;
|
||||
import com.eactive.eai.common.util.ApplicationContextProvider;
|
||||
import com.eactive.eai.transformer.engine.Parser;
|
||||
|
||||
/**
|
||||
* DJBEncrypt / DJBDecrypt — Parser 표현식 통합 테스트.
|
||||
*
|
||||
* DJBCryptoFunctionTest 는 Stack 직접 호출 방식으로 run() 을 검증하고,
|
||||
* 이 클래스는 Parser 를 통해 JEP 수식으로 함수를 호출하는 통합 경로를 검증한다.
|
||||
*/
|
||||
@TestMethodOrder(MethodOrderer.DisplayName.class)
|
||||
@DisplayName("DJBEncrypt / DJBDecrypt — Parser 변수/상수 혼합 테스트")
|
||||
class DJBCryptoFunctionParserTest {
|
||||
|
||||
private static final String MODULE = "AES_MODULE";
|
||||
private static final String PLAIN_TEXT = "hello-djb";
|
||||
private static final byte[] PLAIN_BYTES = PLAIN_TEXT.getBytes(StandardCharsets.UTF_8);
|
||||
private static final byte[] CIPHER_BYTES = {0x01, 0x02, 0x03, 0x04};
|
||||
private static final String ENC_BASE64 = Base64.getEncoder().encodeToString(CIPHER_BYTES);
|
||||
|
||||
private static GenericApplicationContext ctx;
|
||||
private static CryptoModuleService mockService;
|
||||
|
||||
private Parser parser;
|
||||
|
||||
// =========================================================================
|
||||
// 클래스 초기화 — mock CryptoModuleService 를 Spring 컨텍스트에 등록
|
||||
// =========================================================================
|
||||
|
||||
@BeforeAll
|
||||
static void setUpClass() throws Exception {
|
||||
mockService = mock(CryptoModuleService.class);
|
||||
|
||||
ctx = new GenericApplicationContext();
|
||||
ctx.getBeanFactory().registerSingleton("cryptoModuleService", mockService);
|
||||
ctx.registerBeanDefinition("applicationContextProvider",
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ApplicationContextProvider.class)
|
||||
.getBeanDefinition());
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void tearDownClass() {
|
||||
if (ctx != null) ctx.close();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
reset(mockService);
|
||||
when(mockService.encrypt(any(), anyMap(), isNull(), any(byte[].class))).thenReturn(CIPHER_BYTES);
|
||||
when(mockService.decrypt(any(), anyMap(), isNull(), any(byte[].class))).thenReturn(PLAIN_BYTES);
|
||||
|
||||
parser = new Parser();
|
||||
parser.getJep().addFunction("DJBEncrypt", new DJBEncrypt());
|
||||
parser.getJep().addFunction("DJBDecrypt", new DJBDecrypt());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 1. DJBEncrypt
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("1-1. 암호화 — 평문 변수 + 상수 모듈명 → Base64 반환")
|
||||
void encrypt_variablePlain_constantModule() throws Exception {
|
||||
parser.parse("DJBEncrypt(plain, \"" + MODULE + "\")");
|
||||
parser.addVariable("plain", PLAIN_TEXT);
|
||||
|
||||
assertEquals(ENC_BASE64, parser.getValueAsObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("1-2. 암호화 — 평문·모듈명 모두 변수")
|
||||
void encrypt_bothVariables() throws Exception {
|
||||
parser.parse("DJBEncrypt(plain, moduleName)");
|
||||
parser.addVariable("plain", PLAIN_TEXT);
|
||||
parser.addVariable("moduleName", MODULE);
|
||||
|
||||
assertEquals(ENC_BASE64, parser.getValueAsObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("1-3. 암호화 — parse 1회, 변수값 교체 반복 평가")
|
||||
void encrypt_reuseParser_multipleEvaluations() throws Exception {
|
||||
// identity: plainBytes 그대로 반환 → Base64 encoding 경로 검증에 집중
|
||||
when(mockService.encrypt(any(), anyMap(), isNull(), any(byte[].class)))
|
||||
.thenAnswer(inv -> (byte[]) inv.getArgument(3));
|
||||
|
||||
parser.parse("DJBEncrypt(plain, \"" + MODULE + "\")");
|
||||
|
||||
parser.addVariable("plain", "first");
|
||||
String r1 = (String) parser.getValueAsObject();
|
||||
|
||||
parser.addVariable("plain", "second");
|
||||
String r2 = (String) parser.getValueAsObject();
|
||||
|
||||
assertEquals(Base64.getEncoder().encodeToString("first".getBytes(StandardCharsets.UTF_8)), r1);
|
||||
assertEquals(Base64.getEncoder().encodeToString("second".getBytes(StandardCharsets.UTF_8)), r2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("1-4. 암호화 — 한글 평문이 UTF-8 인코딩되어 서비스에 전달된다")
|
||||
void encrypt_koreanPlainText_utf8Encoded() throws Exception {
|
||||
String korean = "한글평문";
|
||||
parser.parse("DJBEncrypt(plain, \"" + MODULE + "\")");
|
||||
parser.addVariable("plain", korean);
|
||||
parser.getValueAsObject();
|
||||
|
||||
verify(mockService).encrypt(eq(MODULE), anyMap(), isNull(),
|
||||
eq(korean.getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 2. DJBDecrypt
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("2-1. 복호화 — Base64 변수 + 상수 모듈명 → 평문 반환")
|
||||
void decrypt_variableEnc_constantModule() throws Exception {
|
||||
parser.parse("DJBDecrypt(enc, \"" + MODULE + "\")");
|
||||
parser.addVariable("enc", ENC_BASE64);
|
||||
|
||||
assertEquals(PLAIN_TEXT, parser.getValueAsObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("2-2. 복호화 — Base64·모듈명 모두 변수")
|
||||
void decrypt_bothVariables() throws Exception {
|
||||
parser.parse("DJBDecrypt(enc, moduleName)");
|
||||
parser.addVariable("enc", ENC_BASE64);
|
||||
parser.addVariable("moduleName", MODULE);
|
||||
|
||||
assertEquals(PLAIN_TEXT, parser.getValueAsObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("2-3. 복호화 — parse 1회, 변수값 교체 반복 평가")
|
||||
void decrypt_reuseParser_multipleEvaluations() throws Exception {
|
||||
// identity: cipherBytes 그대로 반환 → Base64 decoding 경로 검증에 집중
|
||||
when(mockService.decrypt(any(), anyMap(), isNull(), any(byte[].class)))
|
||||
.thenAnswer(inv -> (byte[]) inv.getArgument(3));
|
||||
|
||||
parser.parse("DJBDecrypt(enc, \"" + MODULE + "\")");
|
||||
|
||||
String firstEnc = Base64.getEncoder().encodeToString("first".getBytes(StandardCharsets.UTF_8));
|
||||
String secondEnc = Base64.getEncoder().encodeToString("second".getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
parser.addVariable("enc", firstEnc);
|
||||
assertEquals("first", parser.getValueAsObject());
|
||||
|
||||
parser.addVariable("enc", secondEnc);
|
||||
assertEquals("second", parser.getValueAsObject());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 3. 라운드트립
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("3-1. 라운드트립 — 암호화 결과를 복호화하면 원문과 일치")
|
||||
void roundTrip_encryptThenDecrypt_returnsOriginal() throws Exception {
|
||||
// 암호화
|
||||
parser.parse("DJBEncrypt(plain, \"" + MODULE + "\")");
|
||||
parser.addVariable("plain", PLAIN_TEXT);
|
||||
String encryptedBase64 = (String) parser.getValueAsObject();
|
||||
|
||||
// 복호화
|
||||
parser.parse("DJBDecrypt(enc, \"" + MODULE + "\")");
|
||||
parser.addVariable("enc", encryptedBase64);
|
||||
|
||||
assertEquals(PLAIN_TEXT, parser.getValueAsObject());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("3-2. 라운드트립 — 한글 평문")
|
||||
void roundTrip_koreanPlainText() throws Exception {
|
||||
String korean = "한글평문테스트";
|
||||
when(mockService.encrypt(any(), anyMap(), isNull(), any(byte[].class)))
|
||||
.thenReturn(korean.getBytes(StandardCharsets.UTF_8));
|
||||
when(mockService.decrypt(any(), anyMap(), isNull(), any(byte[].class)))
|
||||
.thenReturn(korean.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
parser.parse("DJBEncrypt(plain, \"" + MODULE + "\")");
|
||||
parser.addVariable("plain", korean);
|
||||
String enc = (String) parser.getValueAsObject();
|
||||
|
||||
parser.parse("DJBDecrypt(enc, \"" + MODULE + "\")");
|
||||
parser.addVariable("enc", enc);
|
||||
assertEquals(korean, parser.getValueAsObject());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 4. 오류 처리
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("4-1. 암호화 — 파라미터 1개이면 예외")
|
||||
void encrypt_singleParam_throwsException() {
|
||||
assertThrows(Exception.class, () -> {
|
||||
parser.parse("DJBEncrypt(plain)");
|
||||
parser.addVariable("plain", PLAIN_TEXT);
|
||||
parser.getValueAsObject();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("4-2. 복호화 — 파라미터 1개이면 예외")
|
||||
void decrypt_singleParam_throwsException() {
|
||||
assertThrows(Exception.class, () -> {
|
||||
parser.parse("DJBDecrypt(enc)");
|
||||
parser.addVariable("enc", ENC_BASE64);
|
||||
parser.getValueAsObject();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("4-3. 복호화 — 유효하지 않은 Base64 상수이면 예외")
|
||||
void decrypt_invalidBase64Constant_throwsException() {
|
||||
assertThrows(Exception.class, () -> {
|
||||
parser.parse("DJBDecrypt(\"!!invalid!!\", \"" + MODULE + "\")");
|
||||
parser.getValueAsObject();
|
||||
});
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -44,8 +44,8 @@ class DJBCryptoFunctionTest {
|
||||
private static GenericApplicationContext ctx;
|
||||
private static CryptoModuleService mockService;
|
||||
|
||||
private DJBDecryt decryt;
|
||||
private DJBEncryt encryt;
|
||||
private DJBDecrypt decryt;
|
||||
private DJBEncrypt encryt;
|
||||
|
||||
// =========================================================================
|
||||
// 클래스 초기화
|
||||
@@ -73,8 +73,8 @@ class DJBCryptoFunctionTest {
|
||||
reset(mockService);
|
||||
when(mockService.decrypt(any(), anyMap(), isNull(), any(byte[].class))).thenReturn(PLAIN_BYTES);
|
||||
when(mockService.encrypt(any(), anyMap(), isNull(), any(byte[].class))).thenReturn(CIPHER_BYTES);
|
||||
decryt = new DJBDecryt();
|
||||
encryt = new DJBEncryt();
|
||||
decryt = new DJBDecrypt();
|
||||
encryt = new DJBEncrypt();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
||||
Reference in New Issue
Block a user