diff --git a/src/main/java/com/eactive/eai/adapter/http/client/impl/filter/OutCryptoFilter.java b/src/main/java/com/eactive/eai/adapter/http/client/impl/filter/OutCryptoFilter.java new file mode 100644 index 0000000..8812c9f --- /dev/null +++ b/src/main/java/com/eactive/eai/adapter/http/client/impl/filter/OutCryptoFilter.java @@ -0,0 +1,87 @@ +package com.eactive.eai.adapter.http.client.impl.filter; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.lang3.StringUtils; + +import com.eactive.eai.adapter.http.filter.AbstractCryptoFilter; + +/** + * HTTP 클라이언트 어댑터용 암복호화 필터 (송신 방향). + * + * doPreFilter : 외부 시스템으로 보내는 요청 암호화 (CRYPTO_ENC_* 프로퍼티 기반) + * doPostFilter : 외부 시스템에서 받은 응답 복호화 (CRYPTO_DEC_* 프로퍼티 기반) + * + * DYNAMIC 키 컨텍스트가 필요한 경우 {@link #buildRuntimeContext}를 오버라이드한다. + * STATIC 키 모듈을 사용하는 경우 빈 Map이 기본값이므로 오버라이드 불필요. + * + * 프로퍼티 설명은 {@link AbstractCryptoFilter} 참조. + * AAD 관련 추가 프로퍼티: + * CRYPTO_AAD_PROP tempProp에서 AAD 값을 조회할 키 이름. + * 미설정 또는 해당 키 없으면 aad=null → IV를 AAD 대체값으로 사용. + */ +public class OutCryptoFilter extends AbstractCryptoFilter implements HttpClientAdapterFilter { + + public static final String PROP_AAD_PROP = "CRYPTO_AAD_PROP"; + + /** + * DYNAMIC 키 도출용 컨텍스트를 구성한다. + * STATIC 키 모듈이면 빈 Map({@code new HashMap<>()})을 반환한다. + * 서브클래스에서 오버라이드하여 tempProp으로부터 값을 추출할 수 있다. + */ + protected Map buildRuntimeContext(Properties prop, Properties tempProp) { + return new HashMap<>(); + } + + /** + * CRYPTO_AAD_PROP 프로퍼티에 지정된 키로 tempProp에서 AAD 값을 조회한다. + * 미설정 또는 값 없으면 null을 반환하여 GCM 기본 동작(IV를 AAD 대체값으로 사용)을 따른다. + */ + protected byte[] buildAad(Properties prop, Properties tempProp) { + String propKey = prop.getProperty(PROP_AAD_PROP); + if (StringUtils.isBlank(propKey) || tempProp == null) { + return null; + } + String value = tempProp.getProperty(propKey); + return StringUtils.isBlank(value) ? null : value.getBytes(StandardCharsets.UTF_8); + } + + @Override + public Object doPreFilter(String adptGrpName, String adptName, Properties prop, Object message, + Properties tempProp) throws Exception { + + String moduleName = required(prop, PROP_MODULE_NAME); + String scope = getProp(prop, PROP_SCOPE, SCOPE_FIELD).toUpperCase(); + String body = toBodyString(message); + Map runtimeCtx = buildRuntimeContext(prop, tempProp); + byte[] aad = buildAad(prop, tempProp); + + if (SCOPE_FIELD.equals(scope)) { + return encryptField(body, moduleName, runtimeCtx, aad, + getProp(prop, PROP_ENC_FROM_PATH, PATH_ROOT), + getProp(prop, PROP_ENC_TO_PATH, PATH_ENCDATA)); + } + return encryptBody(body, moduleName, runtimeCtx, aad); + } + + @Override + public Object doPostFilter(String adptGrpName, String adptName, Properties prop, Object message, + Properties tempProp) throws Exception { + + String moduleName = required(prop, PROP_MODULE_NAME); + String scope = getProp(prop, PROP_SCOPE, SCOPE_FIELD).toUpperCase(); + String body = toBodyString(message); + Map runtimeCtx = buildRuntimeContext(prop, tempProp); + byte[] aad = buildAad(prop, tempProp); + + if (SCOPE_FIELD.equals(scope)) { + return decryptField(body, moduleName, runtimeCtx, aad, + getProp(prop, PROP_DEC_FROM_PATH, PATH_ENCDATA), + getProp(prop, PROP_DEC_TO_PATH, PATH_ROOT)); + } + return decryptBody(body, moduleName, runtimeCtx, aad); + } +} diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/BaseCryptoFilter.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/BaseCryptoFilter.java deleted file mode 100644 index 40dad14..0000000 --- a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/BaseCryptoFilter.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.eactive.eai.adapter.http.dynamic.filter; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import javax.servlet.http.HttpServletRequest; - -/** - * HTTP 어댑터 요청/응답 암복호화 필터 기반 클래스. - * - */ -public class BaseCryptoFilter extends CryptoFilter { - /** - * 빈 Runtime Context를 생성한다. - */ - protected Map buildRuntimeContext(Properties prop, HttpServletRequest request) { - return new HashMap<>(); - } - -} diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/InCryptoFilter.java b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/InCryptoFilter.java new file mode 100644 index 0000000..7425447 --- /dev/null +++ b/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/InCryptoFilter.java @@ -0,0 +1,85 @@ +package com.eactive.eai.adapter.http.dynamic.filter; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; + +import com.eactive.eai.adapter.http.filter.AbstractCryptoFilter; + +/** + * HTTP 서버 어댑터용 암복호화 필터 (수신 방향). + * + * doPreFilter : 수신 요청 복호화 (CRYPTO_DEC_* 프로퍼티 기반) + * doPostFilter : 송신 응답 암호화 (CRYPTO_ENC_* 프로퍼티 기반) + * + * DYNAMIC 키 컨텍스트가 필요한 경우 {@link #buildRuntimeContext}를 오버라이드한다. + * STATIC 키 모듈을 사용하는 경우 빈 Map이 기본값이므로 오버라이드 불필요. + * + * 프로퍼티 설명은 {@link AbstractCryptoFilter} 참조. + */ +public class InCryptoFilter extends AbstractCryptoFilter implements HttpAdapterFilter { + + /** + * DYNAMIC 키 도출용 컨텍스트를 구성한다. + * STATIC 키 모듈이면 빈 Map({@code new HashMap<>()})을 반환한다. + * 서브클래스에서 오버라이드하여 HttpServletRequest로부터 값을 추출할 수 있다. + */ + protected Map buildRuntimeContext(Properties prop, HttpServletRequest request) { + return new HashMap<>(); + } + + /** + * CRYPTO_AAD_HEADER 프로퍼티에 지정된 헤더값을 UTF-8 바이트로 반환한다. + * 미설정 또는 헤더값 없으면 null을 반환하여 GCM 기본 동작(IV를 AAD 대체값으로 사용)을 따른다. + */ + protected byte[] buildAad(Properties prop, HttpServletRequest request) { + String headerName = prop.getProperty(PROP_AAD_HEADER); + if (StringUtils.isBlank(headerName) || request == null) { + return null; + } + String headerValue = request.getHeader(headerName); + return StringUtils.isBlank(headerValue) ? null : headerValue.getBytes(StandardCharsets.UTF_8); + } + + @Override + public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop, + HttpServletRequest request, HttpServletResponse response) throws Exception { + + String moduleName = required(prop, PROP_MODULE_NAME); + String scope = getProp(prop, PROP_SCOPE, SCOPE_FIELD).toUpperCase(); + String body = toBodyString(message); + Map runtimeCtx = buildRuntimeContext(prop, request); + byte[] aad = buildAad(prop, request); + + if (SCOPE_FIELD.equals(scope)) { + return decryptField(body, moduleName, runtimeCtx, aad, + getProp(prop, PROP_DEC_FROM_PATH, PATH_ENCDATA), + getProp(prop, PROP_DEC_TO_PATH, PATH_ROOT)); + } + return decryptBody(body, moduleName, runtimeCtx, aad); + } + + @Override + public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop, + HttpServletRequest request, HttpServletResponse response) throws Exception { + + String moduleName = required(prop, PROP_MODULE_NAME); + String scope = getProp(prop, PROP_SCOPE, SCOPE_FIELD).toUpperCase(); + String body = toBodyString(resultMessage); + Map runtimeCtx = buildRuntimeContext(prop, request); + byte[] aad = buildAad(prop, request); + + if (SCOPE_FIELD.equals(scope)) { + return encryptField(body, moduleName, runtimeCtx, aad, + getProp(prop, PROP_ENC_FROM_PATH, PATH_ROOT), + getProp(prop, PROP_ENC_TO_PATH, PATH_ENCDATA)); + } + return encryptBody(body, moduleName, runtimeCtx, aad); + } +} diff --git a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/CryptoFilter.java b/src/main/java/com/eactive/eai/adapter/http/filter/AbstractCryptoFilter.java similarity index 50% rename from src/main/java/com/eactive/eai/adapter/http/dynamic/filter/CryptoFilter.java rename to src/main/java/com/eactive/eai/adapter/http/filter/AbstractCryptoFilter.java index e8424b7..dd36072 100644 --- a/src/main/java/com/eactive/eai/adapter/http/dynamic/filter/CryptoFilter.java +++ b/src/main/java/com/eactive/eai/adapter/http/filter/AbstractCryptoFilter.java @@ -1,13 +1,10 @@ -package com.eactive.eai.adapter.http.dynamic.filter; +package com.eactive.eai.adapter.http.filter; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.Map; import java.util.Properties; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.apache.commons.lang3.StringUtils; import com.eactive.eai.common.security.CryptoModuleService; @@ -15,30 +12,28 @@ import com.eactive.eai.common.util.Logger; import com.eactive.eai.util.JsonPathUtil; /** - * HTTP 어댑터 요청/응답 암복호화 필터 기반 클래스. + * InCryptoFilter / OutCryptoFilter 공통 기반 클래스. * - * 서브클래스는 {@link #buildRuntimeContext}를 구현하여 - * DYNAMIC 키 도출에 필요한 컨텍스트 맵을 제공한다. - * STATIC 키 모듈을 사용하는 경우 빈 Map을 반환하면 된다. - * (CryptoModuleManager가 KEY_SOURCE_TYPE=STATIC이면 runtimeContext를 무시하고 고정 키를 사용한다.) + * BODY/FIELD 범위 암복호화 로직, 프로퍼티 상수, 유틸리티 메서드를 제공한다. + * HTTP 서버 어댑터용은 {@link InCryptoFilter}, 클라이언트 어댑터용은 {@link OutCryptoFilter} 참조. * - * 어댑터 프로퍼티 키: + * 프로퍼티 키: * CRYPTO_MODULE_NAME 필수. DB에 등록된 암호화 모듈명. - * CRYPTO_SCOPE BODY | FIELD (기본 FIELD) + * CRYPTO_SCOPE BODY | FIELD (기본값: FIELD) * BODY : 메시지 전체를 암복호화 (Base64 인코딩/디코딩) * FIELD : 특정 JSON 경로의 값만 암복호화 * * FIELD 범위 전용: - * CRYPTO_DEC_FROM_PATH 복호화 대상 JSON 경로 (예: /encrypted_data) + * CRYPTO_DEC_FROM_PATH 복호화 대상 JSON 경로 (기본값: /encrypted_data) * CRYPTO_DEC_TO_PATH 복호화 결과 반영 경로. "/" = 전체 body 교체. * CRYPTO_ENC_FROM_PATH 암호화 대상 JSON 경로. "/" = 전체 body 암호화. - * CRYPTO_ENC_TO_PATH 암호화 결과(Base64)를 넣을 JSON 경로 (예: /encrypted_data) + * CRYPTO_ENC_TO_PATH 암호화 결과(Base64)를 넣을 JSON 경로 (기본값: /encrypted_data) * * GCM AAD 전용 (선택): - * CRYPTO_AAD_HEADER AAD로 사용할 HTTP 요청 헤더명 (예: X-Api-Request-Id). + * CRYPTO_AAD_HEADER AAD로 사용할 HTTP 요청 헤더명 (InCryptoFilter 전용). * 미설정 또는 헤더값 없으면 aad=null → IV를 AAD 대체값으로 사용. */ -public abstract class CryptoFilter implements HttpAdapterFilter { +public abstract class AbstractCryptoFilter { protected static Logger logger = Logger.getLogger(Logger.LOGGER_ADAPTER); @@ -50,70 +45,17 @@ public abstract class CryptoFilter implements HttpAdapterFilter { public static final String PROP_ENC_TO_PATH = "CRYPTO_ENC_TO_PATH"; public static final String PROP_AAD_HEADER = "CRYPTO_AAD_HEADER"; - public static final String SCOPE_BODY = "BODY"; - public static final String SCOPE_FIELD = "FIELD"; - public static final String PATH_ROOT = "/"; - public static final String PATH_ENCDATA = "/encrypted_data"; - - // ------------------------------------------------------------------ - // 추상 메서드 - // ------------------------------------------------------------------ - - /** - * DYNAMIC 키 도출에 필요한 runtimeContext 맵을 구성한다. - * STATIC 키 모듈이면 빈 Map({@code new HashMap<>()})을 반환한다. - */ - protected abstract Map buildRuntimeContext(Properties prop, HttpServletRequest request); - - // ------------------------------------------------------------------ - // doPreFilter: 요청 복호화 - // ------------------------------------------------------------------ - - @Override - public Object doPreFilter(String adptGrpName, String adptName, Object message, Properties prop, - HttpServletRequest request, HttpServletResponse response) throws Exception { - - String moduleName = required(prop, PROP_MODULE_NAME); - String scope = getProp(prop, PROP_SCOPE, SCOPE_FIELD).toUpperCase(); - String body = toBodyString(message); - Map runtimeCtx = buildRuntimeContext(prop, request); - byte[] aad = buildAad(prop, request); - - if (SCOPE_FIELD.equals(scope)) { - return decryptField(body, moduleName, runtimeCtx, aad, - getProp(prop, PROP_DEC_FROM_PATH, PATH_ENCDATA), - getProp(prop, PROP_DEC_TO_PATH, PATH_ROOT)); - } - return decryptBody(body, moduleName, runtimeCtx, aad); - } - - // ------------------------------------------------------------------ - // doPostFilter: 응답 암호화 - // ------------------------------------------------------------------ - - @Override - public Object doPostFilter(String adptGrpName, String adptName, Object resultMessage, Properties prop, - HttpServletRequest request, HttpServletResponse response) throws Exception { - - String moduleName = required(prop, PROP_MODULE_NAME); - String scope = getProp(prop, PROP_SCOPE, SCOPE_FIELD).toUpperCase(); - String body = toBodyString(resultMessage); - Map runtimeCtx = buildRuntimeContext(prop, request); - byte[] aad = buildAad(prop, request); - - if (SCOPE_FIELD.equals(scope)) { - return encryptField(body, moduleName, runtimeCtx, aad, - getProp(prop, PROP_ENC_FROM_PATH, PATH_ROOT), - getProp(prop, PROP_ENC_TO_PATH, PATH_ENCDATA)); - } - return encryptBody(body, moduleName, runtimeCtx, aad); - } + public static final String SCOPE_BODY = "BODY"; + public static final String SCOPE_FIELD = "FIELD"; + public static final String PATH_ROOT = "/"; + public static final String PATH_ENCDATA = "/encrypted_data"; // ------------------------------------------------------------------ // 복호화 구현 // ------------------------------------------------------------------ - private String decryptBody(String body, String moduleName, Map runtimeCtx, byte[] aad) throws Exception { + protected String decryptBody(String body, String moduleName, Map runtimeCtx, + byte[] aad) throws Exception { byte[] cipherBytes = Base64.getDecoder().decode(body.trim()); byte[] plainBytes = CryptoModuleService.getInstance().decrypt(moduleName, runtimeCtx, aad, cipherBytes); return new String(plainBytes, StandardCharsets.UTF_8); @@ -123,19 +65,16 @@ public abstract class CryptoFilter implements HttpAdapterFilter { * fromPath의 Base64 값을 복호화하여 toPath에 반영. * toPath = "/" → 복호화된 텍스트로 body 전체 교체. */ - private String decryptField(String body, String moduleName, Map runtimeCtx, byte[] aad, - String fromPath, String toPath) throws Exception { - + protected String decryptField(String body, String moduleName, Map runtimeCtx, + byte[] aad, String fromPath, String toPath) throws Exception { String encBase64 = JsonPathUtil.getValueAtPath(body, fromPath); if (StringUtils.isBlank(encBase64)) { logger.warn("CryptoFilter] 복호화 대상 필드 없음: path=" + fromPath); return body; } - byte[] cipherBytes = Base64.getDecoder().decode(encBase64.trim()); byte[] plainBytes = CryptoModuleService.getInstance().decrypt(moduleName, runtimeCtx, aad, cipherBytes); String plainText = new String(plainBytes, StandardCharsets.UTF_8); - if (PATH_ROOT.equals(toPath)) { return plainText; } @@ -146,7 +85,8 @@ public abstract class CryptoFilter implements HttpAdapterFilter { // 암호화 구현 // ------------------------------------------------------------------ - private String encryptBody(String body, String moduleName, Map runtimeCtx, byte[] aad) throws Exception { + protected String encryptBody(String body, String moduleName, Map runtimeCtx, + byte[] aad) throws Exception { byte[] cipherBytes = CryptoModuleService.getInstance().encrypt(moduleName, runtimeCtx, aad, body.getBytes(StandardCharsets.UTF_8)); return Base64.getEncoder().encodeToString(cipherBytes); @@ -156,9 +96,8 @@ public abstract class CryptoFilter implements HttpAdapterFilter { * fromPath 값을 암호화하여 toPath(Base64)에 반영. * fromPath = "/" → body 전체를 암호화하여 toPath 필드명으로 래핑. */ - private String encryptField(String body, String moduleName, Map runtimeCtx, byte[] aad, - String fromPath, String toPath) throws Exception { - + protected String encryptField(String body, String moduleName, Map runtimeCtx, + byte[] aad, String fromPath, String toPath) throws Exception { String plainText; if (PATH_ROOT.equals(fromPath)) { plainText = body; @@ -169,11 +108,9 @@ public abstract class CryptoFilter implements HttpAdapterFilter { return body; } } - byte[] cipherBytes = CryptoModuleService.getInstance().encrypt(moduleName, runtimeCtx, aad, plainText.getBytes(StandardCharsets.UTF_8)); String encBase64 = Base64.getEncoder().encodeToString(cipherBytes); - if (PATH_ROOT.equals(fromPath)) { String fieldName = toPath.replaceFirst("^/", ""); return "{\"" + fieldName + "\":\"" + encBase64 + "\"}"; @@ -187,12 +124,6 @@ public abstract class CryptoFilter implements HttpAdapterFilter { /** * 필터로 전달되는 message 객체를 JSON 문자열로 변환한다. - *
    - *
  • {@code String} — 그대로 반환
  • - *
  • {@code byte[]} — UTF-8 디코딩
  • - *
  • {@code JSONObject} / 기타 — {@code toString()} 호출 - * (json-simple JSONObject는 toString()이 toJSONString()을 위임함)
  • - *
*/ protected String toBodyString(Object message) { if (message instanceof String) { @@ -204,19 +135,6 @@ public abstract class CryptoFilter implements HttpAdapterFilter { return message.toString(); } - /** - * crypto.aad.header 프로퍼티에 지정된 헤더값을 UTF-8 바이트로 반환한다. - * 프로퍼티 미설정 또는 헤더값 없으면 null을 반환하여 GCM 기본 동작(IV를 AAD 대체값으로 사용)을 따른다. - */ - protected byte[] buildAad(Properties prop, HttpServletRequest request) { - String headerName = prop.getProperty(PROP_AAD_HEADER); - if (StringUtils.isBlank(headerName) || request == null) { - return null; - } - String headerValue = request.getHeader(headerName); - return StringUtils.isBlank(headerValue) ? null : headerValue.getBytes(StandardCharsets.UTF_8); - } - protected String required(Properties prop, String key) { String v = prop.getProperty(key); if (StringUtils.isBlank(v)) { @@ -225,7 +143,7 @@ public abstract class CryptoFilter implements HttpAdapterFilter { return v; } - private String getProp(Properties prop, String key, String defaultVal) { + protected String getProp(Properties prop, String key, String defaultVal) { String v = prop.getProperty(key); return StringUtils.isBlank(v) ? defaultVal : v; } diff --git a/src/test/java/com/eactive/eai/adapter/http/client/impl/filter/OutCryptoFilterTest.java b/src/test/java/com/eactive/eai/adapter/http/client/impl/filter/OutCryptoFilterTest.java new file mode 100644 index 0000000..2f71cb0 --- /dev/null +++ b/src/test/java/com/eactive/eai/adapter/http/client/impl/filter/OutCryptoFilterTest.java @@ -0,0 +1,268 @@ +package com.eactive.eai.adapter.http.client.impl.filter; + +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 java.util.Properties; + +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.adapter.http.filter.AbstractCryptoFilter; +import com.eactive.eai.common.security.CryptoModuleService; +import com.eactive.eai.common.util.ApplicationContextProvider; + +/** + * OutCryptoFilter 단위 테스트. + * + * doPreFilter = 외부로 보내는 요청 암호화 (InCryptoFilter와 반대 방향) + * doPostFilter = 외부에서 받은 응답 복호화 + */ +@TestMethodOrder(MethodOrderer.DisplayName.class) +class OutCryptoFilterTest { + + private static final String MODULE = "TEST_MODULE"; + private static final String PLAIN_STR = "plain-request-body"; + private static final byte[] PLAIN = PLAIN_STR.getBytes(StandardCharsets.UTF_8); + private static final byte[] CIPHER = new byte[]{0x10, 0x20, 0x30, 0x40, 0x50, 0x60}; + private static final String CIPHER_B64 = Base64.getEncoder().encodeToString(CIPHER); + + private static GenericApplicationContext ctx; + private static CryptoModuleService mockService; + private static OutCryptoFilter filter; + + private Properties tempProp; + + @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(); + + filter = new OutCryptoFilter(); + } + + @AfterAll + static void tearDownClass() { + if (ctx != null) ctx.close(); + } + + @BeforeEach + void setUp() throws Exception { + reset(mockService); + tempProp = new Properties(); + + when(mockService.decrypt(anyString(), anyMap(), any(), any(byte[].class))).thenReturn(PLAIN); + when(mockService.encrypt(anyString(), anyMap(), any(), any(byte[].class))).thenReturn(CIPHER); + } + + // ========================================================================= + // 1. buildAad + // ========================================================================= + + @Test + @DisplayName("1-1. buildAad — CRYPTO_AAD_PROP 미설정 → null") + void testBuildAad_noProp_returnsNull() { + assertNull(filter.buildAad(new Properties(), tempProp)); + } + + @Test + @DisplayName("1-2. buildAad — CRYPTO_AAD_PROP 설정, tempProp에 값 없음 → null") + void testBuildAad_propSet_noTempValue_returnsNull() { + Properties prop = new Properties(); + prop.setProperty(OutCryptoFilter.PROP_AAD_PROP, "aadKey"); + + assertNull(filter.buildAad(prop, tempProp)); + } + + @Test + @DisplayName("1-3. buildAad — CRYPTO_AAD_PROP 설정, tempProp에 값 있음 → UTF-8 바이트 반환") + void testBuildAad_propSet_tempValuePresent_returnsByte() { + String aadVal = "aad-value-xyz"; + Properties prop = new Properties(); + prop.setProperty(OutCryptoFilter.PROP_AAD_PROP, "aadKey"); + tempProp.setProperty("aadKey", aadVal); + + assertArrayEquals(aadVal.getBytes(StandardCharsets.UTF_8), filter.buildAad(prop, tempProp)); + } + + // ========================================================================= + // 2. doPreFilter — 암호화 (요청을 외부로 보내기 전) + // ========================================================================= + + @Test + @DisplayName("2-1. BODY scope — 평문 암호화 → Base64 반환") + void testPreFilter_body_encrypt() throws Exception { + Object result = filter.doPreFilter("g", "a", bodyEncryptProps(), PLAIN_STR, tempProp); + + assertEquals(CIPHER_B64, result); + verify(mockService).encrypt(eq(MODULE), anyMap(), isNull(), eq(PLAIN)); + } + + @Test + @DisplayName("2-2. FIELD scope, fromPath='/' — body 전체 암호화 → toPath 필드명으로 래핑") + void testPreFilter_field_encryptFromRoot() throws Exception { + String body = "{\"userId\":\"U001\"}"; + Properties prop = fieldEncryptProps("/", "/encryptedData"); + + Object result = filter.doPreFilter("g", "a", prop, body, tempProp); + + assertEquals("{\"encryptedData\":\"" + CIPHER_B64 + "\"}", result); + } + + @Test + @DisplayName("2-3. FIELD scope — fromPath 평문 암호화 → toPath Base64 반영") + void testPreFilter_field_encryptSpecificPath() throws Exception { + String body = "{\"data\":\"secret\",\"enc\":\"\"}"; + Properties prop = fieldEncryptProps("/data", "/enc"); + + Object result = filter.doPreFilter("g", "a", prop, body, tempProp); + + assertTrue(result.toString().contains("\"enc\":\"" + CIPHER_B64 + "\""), + "toPath에 Base64 암호문이 반영되어야 한다"); + } + + @Test + @DisplayName("2-4. FIELD scope — fromPath 값 없음 → body 그대로 반환") + void testPreFilter_field_missingFromPath_passThrough() throws Exception { + String body = "{\"other\":\"value\"}"; + Properties prop = fieldEncryptProps("/data", "/enc"); + + Object result = filter.doPreFilter("g", "a", prop, body, tempProp); + + assertEquals(body, result); + verifyNoInteractions(mockService); + } + + @Test + @DisplayName("2-5. CRYPTO_MODULE_NAME 누락 — IllegalArgumentException") + void testPreFilter_missingModuleName_throwsException() { + Properties prop = new Properties(); + prop.setProperty(AbstractCryptoFilter.PROP_SCOPE, "BODY"); + + assertThrows(IllegalArgumentException.class, + () -> filter.doPreFilter("g", "a", prop, PLAIN_STR, tempProp)); + } + + // ========================================================================= + // 3. doPostFilter — 복호화 (외부로부터 응답 받은 후) + // ========================================================================= + + @Test + @DisplayName("3-1. BODY scope — Base64 암호문 복호화 → 평문 반환") + void testPostFilter_body_decrypt() throws Exception { + Object result = filter.doPostFilter("g", "a", bodyDecryptProps(), CIPHER_B64, tempProp); + + assertEquals(PLAIN_STR, result); + verify(mockService).decrypt(eq(MODULE), anyMap(), isNull(), eq(CIPHER)); + } + + @Test + @DisplayName("3-2. FIELD scope — fromPath 복호화 → toPath 반영") + void testPostFilter_field_decryptToPath() throws Exception { + String body = "{\"enc\":\"" + CIPHER_B64 + "\",\"result\":\"\"}"; + Properties prop = fieldDecryptProps("/enc", "/result"); + + Object result = filter.doPostFilter("g", "a", prop, body, tempProp); + + assertTrue(result.toString().contains("\"result\":\"" + PLAIN_STR + "\""), + "toPath에 복호화된 값이 반영되어야 한다"); + } + + @Test + @DisplayName("3-3. FIELD scope, toPath='/' — 복호화된 텍스트로 body 전체 교체") + void testPostFilter_field_decryptToRoot() throws Exception { + String body = "{\"enc\":\"" + CIPHER_B64 + "\"}"; + Properties prop = fieldDecryptProps("/enc", "/"); + + Object result = filter.doPostFilter("g", "a", prop, body, tempProp); + + assertEquals(PLAIN_STR, result); + } + + @Test + @DisplayName("3-4. FIELD scope — fromPath 값 없음 → body 그대로 반환") + void testPostFilter_field_missingFromPath_passThrough() throws Exception { + String body = "{\"other\":\"value\"}"; + Properties prop = fieldDecryptProps("/enc", "/result"); + + Object result = filter.doPostFilter("g", "a", prop, body, tempProp); + + assertEquals(body, result); + verifyNoInteractions(mockService); + } + + // ========================================================================= + // 4. AAD (tempProp 경유) + // ========================================================================= + + @Test + @DisplayName("4-1. doPreFilter BODY — CRYPTO_AAD_PROP 설정 시 tempProp 값을 AAD로 전달") + void testPreFilter_body_aadFromTempProp() throws Exception { + String aadVal = "out-aad-value"; + Properties prop = bodyEncryptProps(); + prop.setProperty(OutCryptoFilter.PROP_AAD_PROP, "myAadKey"); + tempProp.setProperty("myAadKey", aadVal); + + filter.doPreFilter("g", "a", prop, PLAIN_STR, tempProp); + + verify(mockService).encrypt(eq(MODULE), anyMap(), + eq(aadVal.getBytes(StandardCharsets.UTF_8)), any(byte[].class)); + } + + @Test + @DisplayName("4-2. doPostFilter BODY — CRYPTO_AAD_PROP 미설정 시 aad=null로 전달") + void testPostFilter_body_noAadProp_nullAad() throws Exception { + filter.doPostFilter("g", "a", bodyDecryptProps(), CIPHER_B64, tempProp); + + verify(mockService).decrypt(eq(MODULE), anyMap(), isNull(), any(byte[].class)); + } + + // ========================================================================= + // 헬퍼 + // ========================================================================= + + private Properties bodyEncryptProps() { + Properties p = new Properties(); + p.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MODULE); + p.setProperty(AbstractCryptoFilter.PROP_SCOPE, "BODY"); + return p; + } + + private Properties bodyDecryptProps() { + return bodyEncryptProps(); + } + + private Properties fieldEncryptProps(String fromPath, String toPath) { + Properties p = new Properties(); + p.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MODULE); + p.setProperty(AbstractCryptoFilter.PROP_SCOPE, "FIELD"); + p.setProperty(AbstractCryptoFilter.PROP_ENC_FROM_PATH, fromPath); + p.setProperty(AbstractCryptoFilter.PROP_ENC_TO_PATH, toPath); + return p; + } + + private Properties fieldDecryptProps(String fromPath, String toPath) { + Properties p = new Properties(); + p.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MODULE); + p.setProperty(AbstractCryptoFilter.PROP_SCOPE, "FIELD"); + p.setProperty(AbstractCryptoFilter.PROP_DEC_FROM_PATH, fromPath); + p.setProperty(AbstractCryptoFilter.PROP_DEC_TO_PATH, toPath); + return p; + } +} diff --git a/src/test/java/com/eactive/eai/adapter/http/dynamic/filter/CryptoFilterHsmIntegrationTest.java b/src/test/java/com/eactive/eai/adapter/http/dynamic/filter/CryptoFilterHsmIntegrationTest.java index 6c9a439..87a7b93 100644 --- a/src/test/java/com/eactive/eai/adapter/http/dynamic/filter/CryptoFilterHsmIntegrationTest.java +++ b/src/test/java/com/eactive/eai/adapter/http/dynamic/filter/CryptoFilterHsmIntegrationTest.java @@ -34,6 +34,8 @@ import org.junit.jupiter.api.TestMethodOrder; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.context.support.GenericApplicationContext; +import com.eactive.eai.adapter.http.dynamic.filter.InCryptoFilter; +import com.eactive.eai.adapter.http.filter.AbstractCryptoFilter; import com.eactive.eai.common.hsm.HsmCryptoService; import com.eactive.eai.common.hsm.HsmManager; import com.eactive.eai.common.property.PropManager; @@ -51,7 +53,7 @@ import com.eactive.eai.data.entity.onl.security.CryptoModuleConfig; * CryptoFilter HSM 연동 통합 테스트 (SoftHSM2 / SunPKCS11) * * SoftHSM2에서 MASTER_KEY를 조회하여 키를 도출한 뒤 - * BaseCryptoFilter / CryptoFilter 의 암복호화 전체 흐름을 검증한다. + * InCryptoFilter 의 암복호화 전체 흐름을 검증한다. * * 사전 조건: * C:\SoftHSM2 에 SoftHSM2 설치 (미설치 시 자동 건너뜀) @@ -94,7 +96,7 @@ public class CryptoFilterHsmIntegrationTest { // 내부 클래스: runtimeContext를 고정값으로 반환하는 필터 // ------------------------------------------------------------------------- - static class ContextAwareCryptoFilter extends CryptoFilter { + static class ContextAwareCryptoFilter extends InCryptoFilter { private final String key; private final String value; @@ -206,17 +208,17 @@ public class CryptoFilterHsmIntegrationTest { } // ========================================================================= - // 1. HsmKeyDerivationStrategy — HSM 마스터키 직접 사용 (BaseCryptoFilter) + // 1. HsmKeyDerivationStrategy — HSM 마스터키 직접 사용 (InCryptoFilter) // ========================================================================= @Test @DisplayName("1-1. FIELD/GCM HsmKey — doPostFilter 암호화 → doPreFilter 복호화 라운드트립") void testHsmGcm_field_roundTrip() throws Exception { - BaseCryptoFilter filter = new BaseCryptoFilter(); + InCryptoFilter filter = new InCryptoFilter(); String original = "{\"acno\":\"1234567890\",\"amount\":\"100000\"}"; Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_MODULE_NAME, MOD_HSM_GCM); + prop.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MOD_HSM_GCM); // SCOPE 기본값 FIELD, 경로 기본값 사용 // 암호화: body 전체 → /encrypted_data 필드 @@ -233,12 +235,12 @@ public class CryptoFilterHsmIntegrationTest { @Test @DisplayName("1-2. BODY/GCM HsmKey — doPostFilter 암호화 → doPreFilter 복호화 라운드트립") void testHsmGcm_body_roundTrip() throws Exception { - BaseCryptoFilter filter = new BaseCryptoFilter(); + InCryptoFilter filter = new InCryptoFilter(); String original = "{\"acno\":\"1234567890\",\"amount\":\"100000\"}"; Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_MODULE_NAME, MOD_HSM_GCM); - prop.setProperty(CryptoFilter.PROP_SCOPE, "BODY"); + prop.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MOD_HSM_GCM); + prop.setProperty(AbstractCryptoFilter.PROP_SCOPE, "BODY"); // 암호화: body 전체 → Base64 암호문 String encrypted = (String) filter.doPostFilter("G", "A", original, prop, mockReq, mockRes); @@ -261,8 +263,8 @@ public class CryptoFilterHsmIntegrationTest { when(mockReq.getHeader("X-Request-Id")).thenReturn(requestId); Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_MODULE_NAME, MOD_HSM_GCM); - prop.setProperty(CryptoFilter.PROP_AAD_HEADER, "X-Request-Id"); + prop.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MOD_HSM_GCM); + prop.setProperty(AbstractCryptoFilter.PROP_AAD_HEADER, "X-Request-Id"); String encrypted = (String) filter.doPostFilter("G", "A", original, prop, mockReq, mockRes); String decrypted = (String) filter.doPreFilter( "G", "A", encrypted, prop, mockReq, mockRes); @@ -285,8 +287,8 @@ public class CryptoFilterHsmIntegrationTest { when(decReq.getHeader("X-Request-Id")).thenReturn("REQ-WRONG"); Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_MODULE_NAME, MOD_HSM_GCM); - prop.setProperty(CryptoFilter.PROP_AAD_HEADER, "X-Request-Id"); + prop.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MOD_HSM_GCM); + prop.setProperty(AbstractCryptoFilter.PROP_AAD_HEADER, "X-Request-Id"); String encrypted = (String) filter.doPostFilter("G", "A", original, prop, encReq, mockRes); @@ -303,11 +305,11 @@ public class CryptoFilterHsmIntegrationTest { @Test @DisplayName("2-1. FIELD/GCM ContextSha256 — 동일 컨텍스트로 암복호화 라운드트립") void testCtxSha256Gcm_field_roundTrip() throws Exception { - CryptoFilter filter = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_A); + InCryptoFilter filter = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_A); String original = "{\"accNo\":\"0011234567890\",\"amount\":\"50000\"}"; Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_MODULE_NAME, MOD_CTX_SHA_GCM); + prop.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MOD_CTX_SHA_GCM); String encrypted = (String) filter.doPostFilter("G", "A", original, prop, mockReq, mockRes); System.out.println("[2-1] encrypted: " + encrypted); @@ -321,12 +323,12 @@ public class CryptoFilterHsmIntegrationTest { @Test @DisplayName("2-2. FIELD/GCM ContextSha256 — 암호화와 다른 컨텍스트로 복호화 시 GCM 인증 실패") void testCtxSha256Gcm_differentContext_throwsException() throws Exception { - CryptoFilter encFilter = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_A); - CryptoFilter decFilter = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_B); + InCryptoFilter encFilter = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_A); + InCryptoFilter decFilter = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_B); String original = "{\"data\":\"sensitive\"}"; Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_MODULE_NAME, MOD_CTX_SHA_GCM); + prop.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MOD_CTX_SHA_GCM); String encrypted = (String) encFilter.doPostFilter("G", "A", original, prop, mockReq, mockRes); @@ -339,13 +341,13 @@ public class CryptoFilterHsmIntegrationTest { @Test @DisplayName("2-3. FIELD/GCM ContextSha256 — 컨텍스트별 독립 암복호화 (GROUP-A, GROUP-B 각각 성공)") void testCtxSha256Gcm_perGroupRoundTrip() throws Exception { - CryptoFilter filterA = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_A); - CryptoFilter filterB = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_B); + InCryptoFilter filterA = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_A); + InCryptoFilter filterB = new ContextAwareCryptoFilter(CTX_KEY, CTX_VAL_B); String plainA = "{\"group\":\"A\",\"amount\":\"1000\"}"; String plainB = "{\"group\":\"B\",\"amount\":\"2000\"}"; Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_MODULE_NAME, MOD_CTX_SHA_GCM); + prop.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MOD_CTX_SHA_GCM); String encA = (String) filterA.doPostFilter("G", "A", plainA, prop, mockReq, mockRes); String encB = (String) filterB.doPostFilter("G", "B", plainB, prop, mockReq, mockRes); diff --git a/src/test/java/com/eactive/eai/adapter/http/dynamic/filter/BaseCryptoFilterTest.java b/src/test/java/com/eactive/eai/adapter/http/dynamic/filter/InCryptoFilterTest.java similarity index 88% rename from src/test/java/com/eactive/eai/adapter/http/dynamic/filter/BaseCryptoFilterTest.java rename to src/test/java/com/eactive/eai/adapter/http/dynamic/filter/InCryptoFilterTest.java index e75423d..334278f 100644 --- a/src/test/java/com/eactive/eai/adapter/http/dynamic/filter/BaseCryptoFilterTest.java +++ b/src/test/java/com/eactive/eai/adapter/http/dynamic/filter/InCryptoFilterTest.java @@ -22,15 +22,16 @@ import org.junit.jupiter.api.TestMethodOrder; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.context.support.GenericApplicationContext; +import com.eactive.eai.adapter.http.filter.AbstractCryptoFilter; import com.eactive.eai.common.security.CryptoModuleService; import com.eactive.eai.common.util.ApplicationContextProvider; /** - * BaseCryptoFilter / CryptoFilter 단위 테스트. + * InCryptoFilter / AbstractCryptoFilter 단위 테스트. * CryptoModuleService는 Mock으로 대체하여 필터 로직(Base64, JSON 경로, 프로퍼티 파싱)만 검증한다. */ @TestMethodOrder(MethodOrderer.DisplayName.class) -class BaseCryptoFilterTest { +class InCryptoFilterTest { private static final String MODULE = "TEST_MODULE"; private static final String PLAIN_STR = "decrypted-plain-text"; @@ -40,7 +41,7 @@ class BaseCryptoFilterTest { private static GenericApplicationContext ctx; private static CryptoModuleService mockService; - private static BaseCryptoFilter filter; + private static InCryptoFilter filter; private HttpServletRequest mockRequest; private HttpServletResponse mockResponse; @@ -56,7 +57,7 @@ class BaseCryptoFilterTest { .getBeanDefinition()); ctx.refresh(); - filter = new BaseCryptoFilter(); + filter = new InCryptoFilter(); } @AfterAll @@ -81,7 +82,7 @@ class BaseCryptoFilterTest { @Test @DisplayName("1-1. buildRuntimeContext — 항상 빈 Map 반환") void testBuildRuntimeContext_returnsEmptyMap() { - Map result = filter.buildRuntimeContext(new Properties(), mockRequest); + Map result = filter.buildRuntimeContext(new Properties(), mockRequest); assertNotNull(result); assertTrue(result.isEmpty()); @@ -101,7 +102,7 @@ class BaseCryptoFilterTest { @DisplayName("2-2. buildAad — 헤더명 설정, 헤더값 없음 → null") void testBuildAad_headerNameSet_noValue_returnsNull() { Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_AAD_HEADER, "X-Api-Request-Id"); + prop.setProperty(AbstractCryptoFilter.PROP_AAD_HEADER, "X-Api-Request-Id"); when(mockRequest.getHeader("X-Api-Request-Id")).thenReturn(null); assertNull(filter.buildAad(prop, mockRequest)); @@ -112,7 +113,7 @@ class BaseCryptoFilterTest { void testBuildAad_headerNameSet_valuePresent_returnsByte() { String headerVal = "req-id-abc123"; Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_AAD_HEADER, "X-Api-Request-Id"); + prop.setProperty(AbstractCryptoFilter.PROP_AAD_HEADER, "X-Api-Request-Id"); when(mockRequest.getHeader("X-Api-Request-Id")).thenReturn(headerVal); assertArrayEquals(headerVal.getBytes(StandardCharsets.UTF_8), filter.buildAad(prop, mockRequest)); @@ -132,17 +133,17 @@ class BaseCryptoFilterTest { } @Test - @DisplayName("3-3. CRYPTO_MODULE_NAME 누락 — IllegalArgumentException") + @DisplayName("3-2. CRYPTO_MODULE_NAME 누락 — IllegalArgumentException") void testPreFilter_missingModuleName_throwsException() { Properties prop = new Properties(); - prop.setProperty(CryptoFilter.PROP_SCOPE, "BODY"); + prop.setProperty(AbstractCryptoFilter.PROP_SCOPE, "BODY"); assertThrows(IllegalArgumentException.class, () -> filter.doPreFilter("g", "a", CIPHER_B64, prop, mockRequest, mockResponse)); } @Test - @DisplayName("3-4. message가 byte[] — UTF-8 디코딩 후 처리") + @DisplayName("3-3. message가 byte[] — UTF-8 디코딩 후 처리") void testPreFilter_body_byteArrayMessage() throws Exception { Object result = filter.doPreFilter("g", "a", CIPHER_B64.getBytes(StandardCharsets.UTF_8), bodyDecryptProps(), mockRequest, mockResponse); @@ -195,7 +196,7 @@ class BaseCryptoFilterTest { // ========================================================================= @Test - @DisplayName("5-1. BODY scope, CRYPTO_ENC_ENABLED=Y — 평문 암호화 → Base64 반환") + @DisplayName("5-1. BODY scope — 평문 암호화 → Base64 반환") void testPostFilter_body_encrypt() throws Exception { String body = "plain-response-body"; Object result = filter.doPostFilter("g", "a", body, bodyEncryptProps(), mockRequest, mockResponse); @@ -252,7 +253,7 @@ class BaseCryptoFilterTest { void testPreFilter_body_aadFromHeader_passedToService() throws Exception { String aadVal = "request-id-xyz"; Properties prop = bodyDecryptProps(); - prop.setProperty(CryptoFilter.PROP_AAD_HEADER, "X-Api-Request-Id"); + prop.setProperty(AbstractCryptoFilter.PROP_AAD_HEADER, "X-Api-Request-Id"); when(mockRequest.getHeader("X-Api-Request-Id")).thenReturn(aadVal); filter.doPreFilter("g", "a", CIPHER_B64, prop, mockRequest, mockResponse); @@ -275,7 +276,7 @@ class BaseCryptoFilterTest { String aadVal = "field-aad-value"; String body = "{\"enc\":\"" + CIPHER_B64 + "\",\"result\":\"\"}"; Properties prop = fieldDecryptProps("/enc", "/result"); - prop.setProperty(CryptoFilter.PROP_AAD_HEADER, "X-Api-Aad"); + prop.setProperty(AbstractCryptoFilter.PROP_AAD_HEADER, "X-Api-Aad"); when(mockRequest.getHeader("X-Api-Aad")).thenReturn(aadVal); filter.doPreFilter("g", "a", body, prop, mockRequest, mockResponse); @@ -290,8 +291,8 @@ class BaseCryptoFilterTest { private Properties bodyDecryptProps() { Properties p = new Properties(); - p.setProperty(CryptoFilter.PROP_MODULE_NAME, MODULE); - p.setProperty(CryptoFilter.PROP_SCOPE, "BODY"); + p.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MODULE); + p.setProperty(AbstractCryptoFilter.PROP_SCOPE, "BODY"); return p; } @@ -301,19 +302,19 @@ class BaseCryptoFilterTest { private Properties fieldDecryptProps(String fromPath, String toPath) { Properties p = new Properties(); - p.setProperty(CryptoFilter.PROP_MODULE_NAME, MODULE); - p.setProperty(CryptoFilter.PROP_SCOPE, "FIELD"); - p.setProperty(CryptoFilter.PROP_DEC_FROM_PATH, fromPath); - p.setProperty(CryptoFilter.PROP_DEC_TO_PATH, toPath); + p.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MODULE); + p.setProperty(AbstractCryptoFilter.PROP_SCOPE, "FIELD"); + p.setProperty(AbstractCryptoFilter.PROP_DEC_FROM_PATH, fromPath); + p.setProperty(AbstractCryptoFilter.PROP_DEC_TO_PATH, toPath); return p; } private Properties fieldEncryptProps(String fromPath, String toPath) { Properties p = new Properties(); - p.setProperty(CryptoFilter.PROP_MODULE_NAME, MODULE); - p.setProperty(CryptoFilter.PROP_SCOPE, "FIELD"); - p.setProperty(CryptoFilter.PROP_ENC_FROM_PATH, fromPath); - p.setProperty(CryptoFilter.PROP_ENC_TO_PATH, toPath); + p.setProperty(AbstractCryptoFilter.PROP_MODULE_NAME, MODULE); + p.setProperty(AbstractCryptoFilter.PROP_SCOPE, "FIELD"); + p.setProperty(AbstractCryptoFilter.PROP_ENC_FROM_PATH, fromPath); + p.setProperty(AbstractCryptoFilter.PROP_ENC_TO_PATH, toPath); return p; } }