gpki 분리

master
mjkhan21 1 year ago
parent 6e9f9a32fa
commit f609575860

@ -48,18 +48,10 @@
<dependencies>
<dependency>
<groupId>cokr.xit.base</groupId>
<artifactId>xit-foundation</artifactId>
<version>23.04.01-SNAPSHOT</version>
<groupId>cokr.xit.interfaces</groupId>
<artifactId>xit-gpki</artifactId>
<version>23.04.01-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>libgpkiapi_jni_1.5</groupId>
<artifactId>libgpkiapi_jni_1.5</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/libgpkiapi_jni_1.5.jar</systemPath>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>

@ -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.
* <ul><li>{@link Config intf-conf/disabled-parking.conf}</li>

@ -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 .
* <ul><li>{@link Config intf-conf/gpki.conf} .</li>
* <li>libgpkiapi_jni_1.5.jar lib .</li>
* </ul>
* @author mjkhan
*/
public class GPKI extends AbstractComponent {
private static final Config conf = Config.get();
private static final HashMap<String, X509Certificate> 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> T call(IntSupplier work, Supplier<T> 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 .
* <pre><code> {
* "license": "이용기관 GPKI API 라이센스 디렉토리",
* "charset": "문자셋",
* "server": {
* "local": "이용기관 서버 CN",
* "targets": "대상기관 서버인증서 아이디, 여러 개일 경우 컴마(,)로 구분"
* },
* "ldapUrl": "대상기관 인증서 다운로드를 위한 LDAP URL",
* "certDir": "서버 인증서, 키 저장 디렉토리",
* "env": {
* "certFile": "이용기관 서버 인증서 파일",
* "privateKeyFile": "이용기관 서버 인증서 키 파일",
* "privateKeyPassword": "이용기관 서버 인증서 비밀번호"
* },
* "sig": {
* "certFile": "이용기관 서버 전자서명 파일",
* "privateKeyFile": "이용기관 서버 전자서명 키 파일",
* "privateKeyPassword": "이용기관 서버 전자서명 비밀번호"
* }
* }</code></pre>
* @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<String, String>
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<String, String> getServer() {
return ifEmpty(server, Collections::emptyMap);
}
public String getLocalServer() {
return getServer().get("local");
}
public List<String> getTargetServers() {
String targets = ifEmpty(getServer().get("targets"), "");
return Stream.of(targets.split(",")).map(String::trim).toList();
}
/**server() .
* @param server server
*/
public void setServer(Map<String, String> server) {
this.server = server;
}
/**env() .
* @return env
*/
public Map<String, String> getEnv() {
return ifEmpty(env, Collections::emptyMap);
}
/**env() .
* @param env env
*/
public void setEnv(Map<String, String> env) {
this.env = env;
}
/**sig() .
* @return sig
*/
public Map<String, String> getSig() {
return ifEmpty(sig, Collections::emptyMap);
}
/**sig() .
* @param sig sig
*/
public void setSig(Map<String, String> sig) {
this.sig = sig;
}
private Map<String, String> 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");
}
}
}

@ -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")

Loading…
Cancel
Save