diff --git a/elink-online-common b/elink-online-common index 3b6b3f6..085dd02 160000 --- a/elink-online-common +++ b/elink-online-common @@ -1 +1 @@ -Subproject commit 3b6b3f6e4c1e211b14e52709c7cdf0ace9bb408b +Subproject commit 085dd024d8fb4ce874fb3a069ccbbfb81ac86c7e diff --git a/src/test/java/com/eactive/eai/custom/security/keyderiv/HsmContextSha256KeyDerivationStrategyTest.java b/src/test/java/com/eactive/eai/custom/security/keyderiv/HsmContextSha256KeyDerivationStrategyTest.java deleted file mode 100644 index eace92e..0000000 --- a/src/test/java/com/eactive/eai/custom/security/keyderiv/HsmContextSha256KeyDerivationStrategyTest.java +++ /dev/null @@ -1,179 +0,0 @@ -package com.eactive.eai.custom.security.keyderiv; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.util.HashMap; -import java.util.Map; - -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - -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.hsm.HsmCryptoService; -import com.eactive.eai.common.security.keyderiv.DerivedKey; -import com.eactive.eai.common.util.ApplicationContextProvider; -import com.eactive.eai.custom.security.keyderiv.strategy.HsmContextSha256KeyDerivationStrategy; - -/** - * HsmContextSha256KeyDerivationStrategy 단위 테스트 - */ -@TestMethodOrder(MethodOrderer.DisplayName.class) -class HsmContextSha256KeyDerivationStrategyTest { - - private static final String HSM_KEY_ALIAS = "MASTER_KEY_AES"; - private static final byte[] MASTER_KEY = "0123456789abcdef".getBytes(StandardCharsets.UTF_8); - - private static GenericApplicationContext ctx; - private static HsmCryptoService mockHsmCryptoService; - private static HsmContextSha256KeyDerivationStrategy strategy; - - private Map params; - private Map runtimeContext; - - @BeforeAll - static void setUpClass() throws Exception { - mockHsmCryptoService = mock(HsmCryptoService.class); - SecretKey mockSecretKey = new SecretKeySpec(MASTER_KEY, "AES"); - when(mockHsmCryptoService.getSecretKey(HSM_KEY_ALIAS)).thenReturn(mockSecretKey); - - ctx = new GenericApplicationContext(); - ctx.getBeanFactory().registerSingleton("hsmCryptoService", mockHsmCryptoService); - ctx.registerBeanDefinition("applicationContextProvider", - BeanDefinitionBuilder.genericBeanDefinition(ApplicationContextProvider.class) - .getBeanDefinition()); - ctx.refresh(); - - strategy = new HsmContextSha256KeyDerivationStrategy(); - } - - @BeforeEach - void setUpParams() { - params = new HashMap<>(); - params.put("hsmKeyAlias", HSM_KEY_ALIAS); - params.put("contextKey", "X-Api-Group-Seq"); - - runtimeContext = new HashMap<>(); - runtimeContext.put("X-Api-Group-Seq", "GROUP_001"); - } - - // ========================================================================= - // 1. deriveKey - // ========================================================================= - - @Test - @DisplayName("1-1. 정상 파라미터 — DerivedKey 반환, 길이 32바이트(SHA-256 고정 출력)") - void testDeriveKey_validParams_returns32ByteKey() throws Exception { - DerivedKey dk = strategy.deriveKey(params, runtimeContext); - - assertNotNull(dk); - assertNotNull(dk.getEncKey()); - assertNotNull(dk.getDecKey()); - assertEquals(32, dk.getEncKey().length, "SHA-256 출력은 항상 32바이트여야 한다"); - } - - @Test - @DisplayName("1-2. SHA-256(masterKey || contextValue) 계산 결과 검증") - void testDeriveKey_sha256ResultIsCorrect() throws Exception { - DerivedKey dk = strategy.deriveKey(params, runtimeContext); - - byte[] contextBytes = "GROUP_001".getBytes(StandardCharsets.UTF_8); - byte[] combined = new byte[MASTER_KEY.length + contextBytes.length]; - System.arraycopy(MASTER_KEY, 0, combined, 0, MASTER_KEY.length); - System.arraycopy(contextBytes, 0, combined, MASTER_KEY.length, contextBytes.length); - byte[] expected = MessageDigest.getInstance("SHA-256").digest(combined); - - assertArrayEquals(expected, dk.getEncKey(), "SHA-256 해싱 결과가 일치해야 한다"); - } - - @Test - @DisplayName("1-3. 대칭 알고리즘 — encKey == decKey") - void testDeriveKey_encKeyEqualsDecKey() throws Exception { - DerivedKey dk = strategy.deriveKey(params, runtimeContext); - - assertArrayEquals(dk.getEncKey(), dk.getDecKey(), "대칭 방식이므로 encKey와 decKey가 동일해야 한다"); - } - - @Test - @DisplayName("1-4. runtimeContext 값 없음 — 빈 문자열로 처리") - void testDeriveKey_missingContextValue_emptyStringUsed() throws Exception { - runtimeContext.remove("X-Api-Group-Seq"); - DerivedKey dk = strategy.deriveKey(params, runtimeContext); - - byte[] expected = MessageDigest.getInstance("SHA-256").digest(MASTER_KEY); - - assertArrayEquals(expected, dk.getEncKey(), "컨텍스트 값 없으면 masterKey만 해싱해야 한다"); - } - - @Test - @DisplayName("1-5. 다른 runtimeContext 값 — 다른 DerivedKey 생성") - void testDeriveKey_differentContextValue_differentKey() throws Exception { - DerivedKey dk1 = strategy.deriveKey(params, runtimeContext); - - runtimeContext.put("X-Api-Group-Seq", "GROUP_002"); - DerivedKey dk2 = strategy.deriveKey(params, runtimeContext); - - assertFalse(java.util.Arrays.equals(dk1.getEncKey(), dk2.getEncKey()), - "컨텍스트 값이 다르면 도출된 키도 달라야 한다"); - } - - @Test - @DisplayName("1-6. 필수 파라미터 누락(hsmKeyAlias) — IllegalArgumentException") - void testDeriveKey_missingHsmKeyAlias_throwsException() { - params.remove("hsmKeyAlias"); - - assertThrows(IllegalArgumentException.class, - () -> strategy.deriveKey(params, runtimeContext), - "hsmKeyAlias 누락 시 IllegalArgumentException이 발생해야 한다"); - } - - @Test - @DisplayName("1-7. 필수 파라미터 누락(contextKey) — IllegalArgumentException") - void testDeriveKey_missingContextKey_throwsException() { - params.remove("contextKey"); - - assertThrows(IllegalArgumentException.class, - () -> strategy.deriveKey(params, runtimeContext), - "contextKey 누락 시 IllegalArgumentException이 발생해야 한다"); - } - - // ========================================================================= - // 2. buildCacheKey - // ========================================================================= - - @Test - @DisplayName("2-1. buildCacheKey — cryptoName:contextValue 형식") - void testBuildCacheKey_format() { - String cacheKey = strategy.buildCacheKey("CRYPTO_A", params, runtimeContext); - - assertEquals("CRYPTO_A:GROUP_001", cacheKey); - } - - @Test - @DisplayName("2-2. buildCacheKey — contextKey 값 없으면 빈 문자열") - void testBuildCacheKey_missingContextValue_emptyString() { - runtimeContext.remove("X-Api-Group-Seq"); - String cacheKey = strategy.buildCacheKey("CRYPTO_A", params, runtimeContext); - - assertEquals("CRYPTO_A:", cacheKey); - } - - @Test - @DisplayName("2-3. buildCacheKey — 다른 cryptoName은 다른 캐시 키") - void testBuildCacheKey_differentCryptoName_differentKey() { - String key1 = strategy.buildCacheKey("CRYPTO_A", params, runtimeContext); - String key2 = strategy.buildCacheKey("CRYPTO_B", params, runtimeContext); - - assertNotEquals(key1, key2); - } -}