feat: HSM 키 파생 전략 클래스 추가 (common 패키지로 이동)
- BaseHsmKeyDerivationStrategy: HSM 마스터키 조회 공통 로직 추상 기반 클래스 - HsmKeyDerivationStrategy: HSM 마스터키 직접 사용 전략 - HsmSha256KeyDerivationStrategy: HSM 마스터키 SHA-256 해싱 도출 전략 - HsmContextSha256KeyDerivationStrategy: HSM 마스터키 + 컨텍스트 SHA-256 해싱 도출 전략 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+40
@@ -0,0 +1,40 @@
|
||||
package com.eactive.eai.common.security.keyderiv.strategy;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import com.eactive.eai.common.hsm.HsmCryptoService;
|
||||
import com.eactive.eai.common.hsm.HsmException;
|
||||
import com.eactive.eai.common.security.keyderiv.KeyDerivationStrategy;
|
||||
import com.eactive.eai.common.util.ApplicationContextProvider;
|
||||
|
||||
/**
|
||||
* HSM 마스터키를 이용하는 전략 클래스들의 기본 클래스
|
||||
*/
|
||||
public abstract class BaseHsmKeyDerivationStrategy implements KeyDerivationStrategy {
|
||||
|
||||
protected static final String PARAM_HSM_KEY_ALIAS = "hsmKeyAlias";
|
||||
|
||||
protected byte[] getHsmKey(Map<String, String> params) throws HsmException {
|
||||
String hsmKeyAlias = required(params, PARAM_HSM_KEY_ALIAS);
|
||||
return getHsmKey(hsmKeyAlias);
|
||||
}
|
||||
|
||||
protected byte[] getHsmKey(String hsmKeyAlias) throws HsmException {
|
||||
SecretKey masterKey = hsmCryptoService().getSecretKey(hsmKeyAlias);
|
||||
return masterKey.getEncoded();
|
||||
}
|
||||
|
||||
private String required(Map<String, String> params, String key) {
|
||||
String value = params.get(key);
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("key_deriv_params 필수값 누락: " + key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private HsmCryptoService hsmCryptoService() {
|
||||
return ApplicationContextProvider.getContext().getBean(HsmCryptoService.class);
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package com.eactive.eai.common.security.keyderiv.strategy;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
|
||||
import com.eactive.eai.common.hsm.HsmCryptoService;
|
||||
import com.eactive.eai.common.security.keyderiv.DerivedKey;
|
||||
import com.eactive.eai.common.security.keyderiv.KeyDerivationStrategy;
|
||||
import com.eactive.eai.common.util.ApplicationContextProvider;
|
||||
|
||||
/**
|
||||
* HSM 마스터키 + 런타임 컨텍스트값을 연결(concatenate)한 뒤 SHA-256 해싱으로 키를 도출하는 전략.
|
||||
* SHA-256 출력은 항상 32바이트(AES-256)이므로 별도 keyLength 파라미터가 불필요하다.
|
||||
*
|
||||
* key_deriv_params (JSON) 예시:
|
||||
* {
|
||||
* "hsmKeyAlias" : "MASTER_KEY_AES",
|
||||
* "contextKey" : "X-Api-Group-Seq" -- runtimeContext에서 꺼낼 키 이름
|
||||
* }
|
||||
*/
|
||||
public class HsmContextSha256KeyDerivationStrategy implements KeyDerivationStrategy {
|
||||
|
||||
private static final String PARAM_HSM_KEY_ALIAS = "hsmKeyAlias";
|
||||
private static final String PARAM_CONTEXT_KEY = "contextKey";
|
||||
|
||||
@Override
|
||||
public DerivedKey deriveKey(Map<String, String> params, Map<String, String> runtimeContext) throws Exception {
|
||||
String hsmKeyAlias = required(params, PARAM_HSM_KEY_ALIAS);
|
||||
String contextKey = required(params, PARAM_CONTEXT_KEY);
|
||||
|
||||
SecretKey masterKey = hsmCryptoService().getSecretKey(hsmKeyAlias);
|
||||
byte[] masterKeyBytes = masterKey.getEncoded();
|
||||
byte[] contextBytes = runtimeContext.getOrDefault(contextKey, "")
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
byte[] combined = new byte[masterKeyBytes.length + contextBytes.length];
|
||||
System.arraycopy(masterKeyBytes, 0, combined, 0, masterKeyBytes.length);
|
||||
System.arraycopy(contextBytes, 0, combined, masterKeyBytes.length, contextBytes.length);
|
||||
|
||||
byte[] derived = MessageDigest.getInstance("SHA-256").digest(combined);
|
||||
return new DerivedKey(derived, derived);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCacheKey(String cryptoName, Map<String, String> params, Map<String, String> runtimeContext) {
|
||||
String contextKey = params.getOrDefault(PARAM_CONTEXT_KEY, "");
|
||||
String contextValue = runtimeContext.getOrDefault(contextKey, "");
|
||||
return cryptoName + ":" + contextValue;
|
||||
}
|
||||
|
||||
private String required(Map<String, String> params, String key) {
|
||||
String value = params.get(key);
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("key_deriv_params 필수값 누락: " + key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private HsmCryptoService hsmCryptoService() {
|
||||
return ApplicationContextProvider.getContext().getBean(HsmCryptoService.class);
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.eactive.eai.common.security.keyderiv.strategy;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.eactive.eai.common.security.keyderiv.DerivedKey;
|
||||
|
||||
/**
|
||||
* HSM 마스터키를 사용하는 전략
|
||||
*
|
||||
* key_deriv_params (JSON) 예시: { "hsmKeyAlias" : "MASTER_KEY_AES"}
|
||||
*/
|
||||
public class HsmKeyDerivationStrategy extends BaseHsmKeyDerivationStrategy {
|
||||
|
||||
@Override
|
||||
public DerivedKey deriveKey(Map<String, String> params, Map<String, String> runtimeContext) throws Exception {
|
||||
byte[] masterKeyBytes = super.getHsmKey(params);
|
||||
return new DerivedKey(masterKeyBytes, masterKeyBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCacheKey(String cryptoName, Map<String, String> params, Map<String, String> runtimeContext) {
|
||||
return cryptoName;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package com.eactive.eai.common.security.keyderiv.strategy;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Map;
|
||||
|
||||
import com.eactive.eai.common.security.keyderiv.DerivedKey;
|
||||
|
||||
/**
|
||||
* HSM 마스터키를 SHA-256 해싱으로 키를 도출하는 전략.
|
||||
* SHA-256 출력은 항상 32바이트(AES-256)이므로 별도 keyLength 파라미터가 불필요하다.
|
||||
*
|
||||
* key_deriv_params (JSON) 예시:
|
||||
* {
|
||||
* "hsmKeyAlias" : "MASTER_KEY_AES"
|
||||
* }
|
||||
*/
|
||||
public class HsmSha256KeyDerivationStrategy extends BaseHsmKeyDerivationStrategy {
|
||||
|
||||
@Override
|
||||
public DerivedKey deriveKey(Map<String, String> params, Map<String, String> runtimeContext) throws Exception {
|
||||
byte[] masterKeyBytes = super.getHsmKey(params);
|
||||
byte[] derived = MessageDigest.getInstance("SHA-256").digest(masterKeyBytes);
|
||||
return new DerivedKey(derived, derived);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCacheKey(String cryptoName, Map<String, String> params, Map<String, String> runtimeContext) {
|
||||
return cryptoName;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user