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.Provider;
import java.security.Security;
import java.util.Base64;

import javax.crypto.SecretKey;

public class HsmManagerSingleTest {

    /**
     * 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";
    	
    	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);
        Provider existing = Security.getProvider(pkcs11Provider.getName());
        Security.addProvider(pkcs11Provider);
        String pin = "1234";
        keyStore = KeyStore.getInstance("PKCS11", pkcs11Provider);
        char[] pinChars = (pin != null) ? pin.toCharArray() : null;
        keyStore.load(null, pinChars);
        
        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);
            	} else {
            		System.out.println("HsmManager] HSM - secretKey null - alias:" + alias + ", secretKey:" + secretKey);
            	}
            }
        }
        System.out.println("HsmManager] HSM 키 목록: [" + aliasList + "]");
	}
}
