From f609575860866553fa746205de2de99bc9509722 Mon Sep 17 00:00:00 2001 From: mjkhan21 Date: Thu, 31 Aug 2023 10:42:36 +0900 Subject: [PATCH] =?UTF-8?q?gpki=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 14 +- .../service/bean/DisabledParkingBean.java | 1 + .../disabledparking/service/bean/GPKI.java | 421 ------------------ .../service/DisabledParkingServiceTest.java | 2 +- 4 files changed, 5 insertions(+), 433 deletions(-) delete mode 100644 src/main/java/cokr/xit/interfaces/disabledparking/service/bean/GPKI.java diff --git a/pom.xml b/pom.xml index 17ddf1a..7a22d8d 100644 --- a/pom.xml +++ b/pom.xml @@ -48,18 +48,10 @@ - cokr.xit.base - xit-foundation - 23.04.01-SNAPSHOT + cokr.xit.interfaces + xit-gpki + 23.04.01-SNAPSHOT - - - libgpkiapi_jni_1.5 - libgpkiapi_jni_1.5 - 1.0 - system - ${project.basedir}/lib/libgpkiapi_jni_1.5.jar - org.mariadb.jdbc diff --git a/src/main/java/cokr/xit/interfaces/disabledparking/service/bean/DisabledParkingBean.java b/src/main/java/cokr/xit/interfaces/disabledparking/service/bean/DisabledParkingBean.java index c5aa5a1..41e647e 100644 --- a/src/main/java/cokr/xit/interfaces/disabledparking/service/bean/DisabledParkingBean.java +++ b/src/main/java/cokr/xit/interfaces/disabledparking/service/bean/DisabledParkingBean.java @@ -27,6 +27,7 @@ import cokr.xit.foundation.AbstractComponent; import cokr.xit.foundation.data.DataObject; import cokr.xit.foundation.data.JSON; import cokr.xit.foundation.web.WebClient; +import cokr.xit.interfaces.gpki.GPKI; /**장애인 표지 조회 Bean. 올바로 동작하려면 *
  • {@link Config intf-conf/disabled-parking.conf}
  • diff --git a/src/main/java/cokr/xit/interfaces/disabledparking/service/bean/GPKI.java b/src/main/java/cokr/xit/interfaces/disabledparking/service/bean/GPKI.java deleted file mode 100644 index 1d477ed..0000000 --- a/src/main/java/cokr/xit/interfaces/disabledparking/service/bean/GPKI.java +++ /dev/null @@ -1,421 +0,0 @@ -package cokr.xit.interfaces.disabledparking.service.bean; - -import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.IntSupplier; -import java.util.function.Supplier; -import java.util.stream.Stream; - -import org.springframework.core.io.ClassPathResource; - -import com.gpki.gpkiapi_jni; -import com.gpki.gpkiapi.GpkiApi; -import com.gpki.gpkiapi.cert.X509Certificate; -import com.gpki.gpkiapi.exception.GpkiApiException; -import com.gpki.gpkiapi.storage.Disk; - -import cokr.xit.foundation.AbstractComponent; -import cokr.xit.foundation.data.JSON; - -/**GPKI(행정전자서명) API 유틸리티. 올바로 동작하려면 - *
    • {@link Config intf-conf/gpki.conf}를 설정해야 한다.
    • - *
    • libgpkiapi_jni_1.5.jar를 lib 디렉토리에 두어야 한다.
    • - *
    - * @author mjkhan - */ -public class GPKI extends AbstractComponent { - private static final Config conf = Config.get(); - private static final HashMap serverCerts = new HashMap<>(); - private static byte[] - envCert, - envKey, - sigCert, - sigKey; - - private gpkiapi_jni gpki; - - /**주어진 문자열을 지정한 아이디의 서버인증서로 암호화하여 반환한다. - * @param serverID 서버인증서 아이디 - * @param data 문자열 - * @return 지정한 아이디의 서버인증서로 암호화한 문자열 - */ - public String encrypt(String serverID, String data) { - if (isEmpty(data)) return ""; - - try { - start(); - - byte[] encrypted = encrypt(serverID, data.getBytes(conf.getCharset())); - return encode(sign(encrypted)); - } catch (Exception e) { - throw runtimeException(e); - } finally { - finish(); - } - } - - /**주어진 암호화된 문자열을 복호화하여 반환한다. - * @param encrypted 암호화된 문자열 - * @return 복호화한 문자열 - */ - public String decrypt(String encrypted) { - if (isEmpty(encrypted)) return ""; - - try { - start(); - - byte[] validated = validate(decode(encrypted)); - return new String(decrypt(validated), conf.getCharset()); - } catch (Exception e) { - throw runtimeException(e); - } finally { - finish(); - } - } - - private static void call(gpkiapi_jni gpki, IntSupplier task, String msg) throws Exception { - int result = task.getAsInt(); - if (result == 0) return; - - String message = isEmpty(msg) ? "" : msg + ": "; - message += gpki != null ? gpki.sDetailErrorString : "errorCode = " + result; - - throw new Exception(message); - } - - private static void init() { - if (!serverCerts.isEmpty()) return; - - try { - GpkiApi.init(conf.license); - gpkiapi_jni gpki = getGpki(); - call(gpki, () -> gpki.API_GetInfo(), null); - - for (String serverID: conf.getTargetServers()) - load(gpki, serverID); - - envCert = Disk.readCert(conf.getCertFile("env")).getCert(); - envKey = Disk.readPriKey(conf.getPrivateKeyFile("env"), conf.getPrivateKeyPassword("env")).getKey(); - - sigCert = Disk.readCert(conf.getCertFile("sig")).getCert(); - sigKey = Disk.readPriKey(conf.getPrivateKeyFile("sig"), conf.getPrivateKeyPassword("sig")).getKey(); - - finish(gpki); - } catch (Exception e) { - throw runtimeException(e); - } - } - - private static gpkiapi_jni getGpki() throws Exception{ - gpkiapi_jni gpki = new gpkiapi_jni(); - call(gpki, () -> gpki.API_Init(conf.license), null); - return gpki; - } - - private static void finish(gpkiapi_jni gpki) { - if (gpki == null) return; - - try { - call(gpki, () -> gpki.API_Finish(), null); - } catch (Exception e) { - throw runtimeException(e); - } - } - - private static void load(gpkiapi_jni gpki, String serverID) throws Exception { - X509Certificate cert = null; - String certFile = conf.certDir + File.separator + serverID + ".cer"; - try { - cert = Disk.readCert(certFile); - } catch (GpkiApiException e) { - cert = null; - } - - if (cert == null && !isEmpty(conf.ldapUrl)) { - String uri = serverID.charAt(3) > '9' ? - ",ou=Group of Server,o=Public of Korea,c=KR" : - ",ou=Group of Server,o=Government of Korea,c=KR"; - - call(gpki, - () -> gpki.LDAP_GetAnyDataByURL("userCertificate;binary", conf.ldapUrl + serverID + uri), - null - ); - - cert = new X509Certificate(gpki.baReturnArray); - Disk.writeCert(certFile, cert); - } - - if (cert != null) - serverCerts.put(serverID, cert); - } - - private static X509Certificate getCert(String serverID) { - X509Certificate cert = serverCerts.get(serverID); - if (cert == null) - throw new RuntimeException(String.format("%s not found for %s", X509Certificate.class.getSimpleName(), serverID)); - return cert; - } - - private T call(IntSupplier work, Supplier result, String message) { - boolean finish = start(); - - try { - call(gpki, work, message); - return result.get(); - } catch (Exception e) { - throw runtimeException(e); - } finally { - if (finish) - finish(); - } - } - - private byte[] encrypt(String serverID, byte[] data) { - return call( - () -> { - X509Certificate cert = getCert(serverID); - return gpki.CMS_MakeEnvelopedData(cert.getCert(), data, gpkiapi_jni.SYM_ALG_NEAT_CBC); - }, - () -> gpki.baReturnArray, - "Encryption failed" - ); - } - - private byte[] decrypt(byte[] encrypted) { - return call( - () -> gpki.CMS_ProcessEnvelopedData(envCert, envKey, encrypted), - () -> gpki.baReturnArray, - "Decryption failed" - ); - } - - private byte[] sign(byte[] data) { - return call( - () -> gpki.CMS_MakeSignedData(sigCert, sigKey, data, null), - () -> gpki.baReturnArray, - "Fail to sign message" - ); - } - - private byte[] validate(byte[] signed) { - return call( - () -> gpki.CMS_ProcessSignedData(signed), - () -> gpki.baData, - "Validation failed" - ); - } - - private String encode(byte[] data) { - return call( - () -> gpki.BASE64_Encode(data), - () -> gpki.sReturnString, - "Encoding failed" - ); - } - - private byte[] decode(String encoded) { - return call( - () -> gpki.BASE64_Decode(encoded), - () -> gpki.baReturnArray, - "Decoding failed" - ); - } - - private boolean start() { - if (gpki != null) return false; - - try { - init(); - gpki = getGpki(); - return true; - } catch (Exception e) { - throw runtimeException(e); - } - } - - private void finish() { - if (gpki == null) return; - - finish(gpki); - gpki = null; - } - - /**GPKI 설정파일(intf-conf/gpki.conf)을 로드한다. - * 설정 항목은 JSON 포맷으로 된 다음 내용을 적재한다. - *
     {
    -	 *     "license": "이용기관 GPKI API 라이센스 디렉토리",
    -	 *     "charset": "문자셋",
    -	 *     "server": {
    -	 *         "local": "이용기관 서버 CN",
    -	 *         "targets": "대상기관 서버인증서 아이디, 여러 개일 경우 컴마(,)로 구분"
    -	 *     },
    -	 *     "ldapUrl": "대상기관 인증서 다운로드를 위한 LDAP URL",
    -	 *     "certDir": "서버 인증서, 키 저장 디렉토리",
    -	 *     "env": {
    -	 *         "certFile": "이용기관 서버 인증서 파일",
    -	 *         "privateKeyFile": "이용기관 서버 인증서 키 파일",
    -	 *         "privateKeyPassword": "이용기관 서버 인증서 비밀번호"
    -	 *     },
    -	 *     "sig": {
    -	 *         "certFile": "이용기관 서버 전자서명 파일",
    -	 *         "privateKeyFile": "이용기관 서버 전자서명 키 파일",
    -	 *         "privateKeyPassword": "이용기관 서버 전자서명 비밀번호"
    -	 *     }
    -	 * }
    - * @author mjkhan - */ - public static class Config extends AbstractComponent { - private static Config conf; - - public static Config get() { - if (conf == null) - try { - ClassPathResource res = new ClassPathResource("intf-conf/gpki.conf"); - conf = new JSON().parse(res.getInputStream(), Config.class); - } catch (Exception e) { - throw runtimeException(e); - } - return conf; - } - - private String - charset, - license, - ldapUrl, - certDir; - private Map - server, - env, - sig; - - /**charset을(를) 반환한다. - * @return charset - */ - public String getCharset() { - return charset; - } - - /**charset을(를) 설정한다. - * @param charset charset - */ - public void setCharset(String charset) { - this.charset = charset; - } - - /**license을(를) 반환한다. - * @return license - */ - public String getLicense() { - return license; - } - - /**license을(를) 설정한다. - * @param license license - */ - public void setLicense(String license) { - this.license = license; - } - - /**ldapUrl을(를) 반환한다. - * @return ldapUrl - */ - public String getLdapUrl() { - return ldapUrl; - } - - /**ldapUrl을(를) 설정한다. - * @param ldapUrl ldapUrl - */ - public void setLdapUrl(String ldapUrl) { - this.ldapUrl = ldapUrl; - } - - /**certDir을(를) 반환한다. - * @return certDir - */ - public String getCertDir() { - return certDir; - } - - /**certDir을(를) 설정한다. - * @param certDir certDir - */ - public void setCertDir(String certDir) { - this.certDir = certDir; - } - - /**server을(를) 반환한다. - * @return server - */ - public Map getServer() { - return ifEmpty(server, Collections::emptyMap); - } - - public String getLocalServer() { - return getServer().get("local"); - } - - public List getTargetServers() { - String targets = ifEmpty(getServer().get("targets"), ""); - return Stream.of(targets.split(",")).map(String::trim).toList(); - } - - /**server을(를) 설정한다. - * @param server server - */ - public void setServer(Map server) { - this.server = server; - } - - /**env을(를) 반환한다. - * @return env - */ - public Map getEnv() { - return ifEmpty(env, Collections::emptyMap); - } - - /**env을(를) 설정한다. - * @param env env - */ - public void setEnv(Map env) { - this.env = env; - } - - /**sig을(를) 반환한다. - * @return sig - */ - public Map getSig() { - return ifEmpty(sig, Collections::emptyMap); - } - - /**sig을(를) 설정한다. - * @param sig sig - */ - public void setSig(Map sig) { - this.sig = sig; - } - - private Map getCredentials(String type) { - switch (type) { - case "env": return getEnv(); - case "sig": return getSig(); - default: throw new IllegalArgumentException(type); - } - } - - public String getCertFile(String type) { - return certDir + File.separator + getCredentials(type).get("certFile"); - } - - public String getPrivateKeyFile(String type) { - return certDir + File.separator + getCredentials(type).get("privateKeyFile"); - } - - public String getPrivateKeyPassword(String type) { - return getCredentials(type).get("privateKeyPassword"); - } - } -} \ No newline at end of file diff --git a/src/test/java/cokr/xit/interfaces/disabledparking/service/DisabledParkingServiceTest.java b/src/test/java/cokr/xit/interfaces/disabledparking/service/DisabledParkingServiceTest.java index d7f2736..586bc11 100644 --- a/src/test/java/cokr/xit/interfaces/disabledparking/service/DisabledParkingServiceTest.java +++ b/src/test/java/cokr/xit/interfaces/disabledparking/service/DisabledParkingServiceTest.java @@ -9,7 +9,7 @@ import org.junit.jupiter.api.Test; import cokr.xit.foundation.test.TestSupport; import cokr.xit.interfaces.disabledparking.service.bean.DisabledParkingBean; -import cokr.xit.interfaces.disabledparking.service.bean.GPKI; +import cokr.xit.interfaces.gpki.GPKI; public class DisabledParkingServiceTest extends TestSupport { @Resource(name = "disabledParkingBean")