Files
elink-online-common/src/test/java/com/eactive/eai/common/hsm/HsmAddKeyTest.java
T
2026-06-30 09:43:10 +09:00

197 lines
8.1 KiB
Java

package com.eactive.eai.common.hsm;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.spec.InvalidKeySpecException;
import java.util.Base64;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.SecretKeySpec;
public class HsmAddKeyTest {
/**
* JDK 버전에 따라 SunPKCS11 Provider 를 생성한다.
*
* JDK 8 : SunPKCS11(InputStream) 생성자를 리플렉션으로 호출 JDK 9+:
* Provider.configure(configFilePath) 를 리플렉션으로 호출
*
* 두 경로 모두 리플렉션을 사용하므로 컴파일 타임에 JDK 버전 의존성이 없다.
*/
static Provider createProvider(String cfgContent) throws Exception {
String javaVersion = System.getProperty("java.version");
if (javaVersion.startsWith("1.")) {
// JDK 8: new SunPKCS11(InputStream)
InputStream is = new ByteArrayInputStream(cfgContent.getBytes("UTF-8"));
return (Provider) Class.forName("sun.security.pkcs11.SunPKCS11").getConstructor(InputStream.class)
.newInstance(is);
} else {
// JDK 9+: Security.getProvider("SunPKCS11").configure(configFilePath)
// configure() 는 JDK 9 에서 추가된 메서드이므로 리플렉션으로 호출
File tmp = File.createTempFile("pkcs11-hsm-", ".cfg");
tmp.deleteOnExit();
Files.write(tmp.toPath(), cfgContent.getBytes("UTF-8"));
Provider base = Security.getProvider("SunPKCS11");
Method configure = Provider.class.getMethod("configure", String.class);
return (Provider) configure.invoke(base, tmp.getAbsolutePath());
}
}
public static void main(String[] args) throws Exception {
// String config = "name = ProtectServer\r\n"
// + "library = /usr/safenet/protecttoolkit5/ptk/lib/libcryptoki.so\r\n"
// + "slot = 0";
// String config = "name = SoftHSM\r\nlibrary = C:/SoftHSM2/lib/softhsm2-x64.dll\r\nslotListIndex = 0\r\n";
String config = "name = SoftHSM\r\n"
+ "library = C:/SoftHSM2/lib/softhsm2-x64.dll\r\n"
+ "slotListIndex = 0\r\n"
+ "attributes(*, CKO_SECRET_KEY, CKK_AES) = {\r\n"
+ " CKA_TOKEN = true\r\n"
+ " CKA_SENSITIVE = false\r\n"
+ " CKA_EXTRACTABLE = true\r\n"
+ " CKA_ENCRYPT = true\r\n"
+ " CKA_DECRYPT = true\r\n"
+ "}\r\n";
KeyStore keyStore;
// Provider pkcs11Provider = HsmManagerSingleTest.createProvider(config);
InputStream is = new ByteArrayInputStream(config.getBytes("UTF-8"));
Provider pkcs11Provider = (Provider) Class.forName("sun.security.pkcs11.SunPKCS11")
.getConstructor(InputStream.class).newInstance(is);
Security.addProvider(pkcs11Provider);
String pin = "1234";
keyStore = KeyStore.getInstance("PKCS11", pkcs11Provider);
char[] pinChars = (pin != null) ? pin.toCharArray() : null;
keyStore.load(null, pinChars);
// addKey("20250916_openapi_erpbank_t", "55187afc5d36a2e3b71f3bf992947389964ac5ea0bc8ebe2297265134fa34cb9",
// keyStore, pkcs11Provider);
// addKey("20240401_openapi_kakaobank_t", "f009328cb94f5c866ff730735ce8031b43ca84f9266ced641b4046c6a5c21038",
// keyStore, pkcs11Provider);
// addKey("20250620_openapi_coocon_t", "3e7a7673392c424e58265c7b6f2e596f7a59542b277472704c3d5d6c70226673",
// keyStore, pkcs11Provider);
// addKey("20211221_openapi_kakaopay_t", "23667b665037785c3c312a414b6c566d2f3832476b254646727c4d703d484534",
// keyStore, pkcs11Provider);
//
// addKey("20250916_openapi_erpbank_t_0", "55187afc5d36a2e3b71f3bf992947389964ac5ea0bc8ebe2297265134fa34cb9",
// keyStore, pkcs11Provider);
// addKey("20240401_openapi_kakaobank_t_0", "f009328cb94f5c866ff730735ce8031b43ca84f9266ced641b4046c6a5c21038",
// keyStore, pkcs11Provider);
// addKey("20250620_openapi_coocon_t_0", "3e7a7673392c424e58265c7b6f2e596f7a59542b277472704c3d5d6c70226673",
// keyStore, pkcs11Provider);
// addKey("20211221_openapi_kakaopay_t_0", "23667b665037785c3c312a414b6c566d2f3832476b254646727c4d703d484534",
// keyStore, pkcs11Provider);
addKey("20260518_openapi_npayloan_t", "7f7f6608a0c2f28d9a7e53f81b265f12b46f893ffcecc253bdc0561338e10208",
keyStore, pkcs11Provider);
addKey("20260518_openapi_npayloan_iv_t", "b797008af20f0e1eda6c71d14bec5bb7",
keyStore, pkcs11Provider);
addKey("20241022_openapi_toss_t", "3051557a6c786475536c4f532f4c6b6b436a4c312f42434947764d336b66306e",
keyStore, pkcs11Provider);
addKey("20250307_openapi_tossbank_t", "48b8465313d6fc529a9f16c3347cde55a663efaf9ade41429c1cb484398bcf93",
keyStore, pkcs11Provider);
addKey("20250307_openapi_tossbank_iv_t", "2bdf93b1f872962d2aa2f890e179e3e0",
keyStore, pkcs11Provider);
addKey("20240524_openapi_banksalad_t", "466166733957513862616a646e55686a353759554c784e4a6463783279767035",
keyStore, pkcs11Provider);
System.out.println("HsmManager] 초기화 완료. Provider=" + pkcs11Provider.getName());
java.util.Enumeration<String> aliases = keyStore.aliases();
StringBuilder aliasList = new StringBuilder();
while (aliases.hasMoreElements()) {
if (aliasList.length() > 0)
aliasList.append(", ");
String alias = aliases.nextElement();
aliasList.append(alias);
java.security.Key key = keyStore.getKey(alias, null);
if (key instanceof SecretKey) {
SecretKey secretKey = (SecretKey) key;
if (secretKey.getEncoded() != null) {
String encBase64 = Base64.getEncoder().encodeToString(secretKey.getEncoded());
System.out.println("HsmManager] HSM - alias:" + alias + ", base64:" + encBase64 + ", secretKey:" + secretKey);
} else {
System.out
.println("HsmManager] HSM - secretKey null - alias:" + alias + ", secretKey:" + secretKey);
}
}
}
System.out.println("HsmManager] HSM 키 목록: [" + aliasList + "]");
}
private static void addKey(String keyAlias, String keyValue, KeyStore keyStore, Provider pkcs11Provider)
throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, InvalidKeySpecException {
byte[] keyBytes = hexToBytes(keyValue);
SecretKeySpec spec = new SecretKeySpec(keyBytes, "AES");
SecretKeyFactory factory = SecretKeyFactory.getInstance("AES", pkcs11Provider);
SecretKey fixedKey = (SecretKey) factory.generateSecret(spec);
// SecretKey fixedKey = new SecretKeySpec(keyBytes, "AES");
keyStore.setKeyEntry(keyAlias, fixedKey, null, null);
// // 2. wrapping key 생성 (최초 1회만 — 이후엔 재사용)
// KeyGenerator wrapKeyGen = KeyGenerator.getInstance("AES", pkcs11Provider);
// wrapKeyGen.init(256);
// SecretKey wrappingKey = wrapKeyGen.generateKey();
//
// // 3. 테스트 환경 key 값 지정
// byte[] testKeyBytes = hexToBytes(keyValue);
// SecretKey targetKeySpec = new SecretKeySpec(testKeyBytes, "AES");
//
// // 4. wrap
// Cipher wrapCipher = Cipher.getInstance("AESWRAP", pkcs11Provider);
// wrapCipher.init(Cipher.WRAP_MODE, wrappingKey);
// byte[] wrapped = wrapCipher.wrap(targetKeySpec);
//
// // 5. unwrap → SoftHSM2 내부에 실제 등록
// Cipher unwrapCipher = Cipher.getInstance("AESWRAP", pkcs11Provider);
// unwrapCipher.init(Cipher.UNWRAP_MODE, wrappingKey);
// SecretKey hsmKey = (SecretKey) unwrapCipher.unwrap(wrapped, "AES", Cipher.SECRET_KEY
//
// );
//
// // 6. 평문 byte 배열 즉시 제거
// Arrays.fill(testKeyBytes, (byte) 0);
//
// System.out.println("Key 등록 완료: " + hsmKey.getAlgorithm() + " / " + hsmKey.getFormat());
//
// // 7. 등록 확인 — alias 지정해서 KeyStore에 올리고 싶으면:
// keyStore.setKeyEntry(keyAlias, hsmKey, null, null);
}
private static byte[] hexToBytes(String hex) {
int len = hex.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + Character.digit(hex.charAt(i + 1), 16));
}
return data;
}
public static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}
}