[성현모] VPKI 프로젝트 Import
This commit is contained in:
18
Projects/VPKI/Doc/java/vpki/ConfigureInfo.java
Normal file
18
Projects/VPKI/Doc/java/vpki/ConfigureInfo.java
Normal file
@ -0,0 +1,18 @@
|
||||
package vpki;
|
||||
|
||||
public class ConfigureInfo {
|
||||
public static String KEY_ALGORITHM = "secp256r1";
|
||||
public static String SIGN_ALGORITHM = "SHA256withECDSA";
|
||||
|
||||
public static String CA_URL = "http://127.0.0.1:8080";
|
||||
public static String HASHEDCSR = "/api/v1/tbscsr";
|
||||
public static String CERTIFICATE = "/api/v1/certificate";
|
||||
public static String VERITYRESULT = "/api/v1/verifyresult";
|
||||
|
||||
public static String CA_CERT = "MIICszCCAlmgAwIBAgIUHxrrBdc1lvNKymblQjb06G6MSJYwCgYIKoZIzj0EAwIwPjELMAkGA1UEBhMCS1IxDTALBgNVBAoMBEhLTUMxDDAKBgNVBAsMA0VDQzESMBAGA1UEAwwJUm9vdENBMDAxMCAXDTE5MDYxMjA2MTUxNVoYDzIwNzkwNjEyMjM1OTU5WjA8MQswCQYDVQQGEwJLUjENMAsGA1UECgwESEtNQzEMMAoGA1UECwwDRUNDMRAwDgYDVQQDDAdDQTAxMDAxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEB0KuXigZeI7U1McUnjEhYGL4g7zsvyzoNl8SMJ0oPxJgiXka+A37JjK4L/P85bAG7N4C6IYuSem99P0C0vt0K6OCATMwggEvMB8GA1UdIwQYMBaAFLW9YfqauBG22R0cDywt08OqFD99MB0GA1UdDgQWBBQl67U3b8S3sG1J/ukFKlGcqPpw8DAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8vY3JsLmhtY2ttYy5jby5rci9FQ0MvUm9vdC9hcmwvQXJsMURwMS5jcmwwgYUGCCsGAQUFBwEBBHkwdzA7BggrBgEFBQcwAoYvaHR0cDovL2NybC5obWNrbWMuY28ua3IvRUNDL2NlcnQvaGttY3Jvb3RjYS5kZXIwOAYIKwYBBQUHMAGGLGh0dHA6Ly9ydG9jc3AuaG1ja21jLmNvLmtyL0VDQy9PQ1NQL2hrbWNvY3NwMAoGCCqGSM49BAMCA0gAMEUCICfXVV8IhFBXkaOHkg2Wk883y9r3B5rPtDV9JKhUQuBXAiEAug5R/broK+ZjM3vYdU7dndBfMFkOYtCa1NBdq6ie/Fs=";
|
||||
public static String OCSP_URL = "http://ocsp.hmckmc.co.kr/ECC/OCSP/CA01001";
|
||||
|
||||
public static String WMI = "HMC";
|
||||
|
||||
public static String revokeDN = "cn=%s,ou=P001,ou=C001,ou=ECC,o=HKMC,c=KR,dc=OEM";
|
||||
}
|
||||
289
Projects/VPKI/Doc/java/vpki/VpkiApplication.java
Normal file
289
Projects/VPKI/Doc/java/vpki/VpkiApplication.java
Normal file
@ -0,0 +1,289 @@
|
||||
package vpki;
|
||||
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.util.encoders.Base64;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import vpki.core.HttpFactory;
|
||||
import vpki.core.PkiFactory;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.security.spec.ECParameterSpec;
|
||||
import java.security.spec.ECPoint;
|
||||
import java.security.spec.ECPublicKeySpec;
|
||||
|
||||
public class VpkiApplication {
|
||||
JSONObject jSONObject;
|
||||
String macAddress;
|
||||
String wmi;
|
||||
String iftid;
|
||||
String pubKeyHex;
|
||||
|
||||
KeyPair keyPair;
|
||||
|
||||
String hashedCsrStr;
|
||||
String pcid;
|
||||
|
||||
public void init() throws Exception {
|
||||
keyPair = PkiFactory.generateKeyPair(ConfigureInfo.KEY_ALGORITHM);
|
||||
jSONObject = new JSONObject();
|
||||
|
||||
macAddress = "9C36F800001E";
|
||||
wmi = "KMH";
|
||||
iftid = "ift01";
|
||||
|
||||
}
|
||||
|
||||
public JSONObject getCsr() throws Exception {
|
||||
|
||||
|
||||
ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic();
|
||||
byte[] tmp = new byte[]{0x04};
|
||||
byte[] x = publicKey.getW().getAffineX().toByteArray(); //getQ().getXCoord().getEncoded();
|
||||
byte[] y = publicKey.getW().getAffineY().toByteArray(); //getQ().getYCoord().getEncoded();
|
||||
byte[] xy = new byte[x.length+y.length+1];
|
||||
|
||||
System.out.println("Client PubKey: " + Base64.toBase64String(keyPair.getPublic().getEncoded()));
|
||||
System.out.println("PubKey x.length: " + x.length);
|
||||
System.out.println("PubKey y.length: " + y.length);
|
||||
System.out.println("Client PriKey: " + Base64.toBase64String(keyPair.getPrivate().getEncoded()));
|
||||
|
||||
System.arraycopy(tmp, 0, xy, 0, 1);
|
||||
if(x.length > 32) {
|
||||
System.arraycopy(x, 1, xy, 1, 32);
|
||||
}else{
|
||||
System.arraycopy(x, 0, xy, 1, 32);
|
||||
}
|
||||
if(y.length > 32) {
|
||||
System.arraycopy(y, 1, xy, 33, 32);
|
||||
}else{
|
||||
System.arraycopy(y, 0, xy, 33, 32);
|
||||
}
|
||||
|
||||
|
||||
//hashed CSR Request
|
||||
jSONObject.put("iftid",iftid);
|
||||
jSONObject.put("macaddr",macAddress);
|
||||
jSONObject.put("publickey", Base64.toBase64String(xy));
|
||||
jSONObject.put("wmi",wmi);
|
||||
|
||||
String hashedCSRReqStr = jSONObject.toJSONString();
|
||||
System.out.println(">> hashedCSR Request :" + hashedCSRReqStr);
|
||||
byte[] hashedCSRBytes = HttpFactory.sendPost(hashedCSRReqStr.getBytes(), HttpFactory.REQUESTTYPE.HASHEDCSR);
|
||||
System.out.println(">> hashedCSR Response :" + new String(hashedCSRBytes));
|
||||
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
jSONObject = (JSONObject) jsonParser.parse(new String(hashedCSRBytes));
|
||||
String status = (String) jSONObject.get("status");
|
||||
|
||||
if(!status.equalsIgnoreCase("success")) {
|
||||
throw new Exception((String) jSONObject.get("message"));
|
||||
}
|
||||
|
||||
return (JSONObject) jSONObject.get("data");
|
||||
}
|
||||
|
||||
public JSONObject getCertificate() throws Exception {
|
||||
//Certificate Request
|
||||
byte[] signedCSRBytes = PkiFactory.signECDSAHashedValue(Base64.decode(hashedCsrStr), keyPair.getPrivate());
|
||||
boolean verify1 = PkiFactory.verifyECDSAHashedValue(Base64.decode(hashedCsrStr), keyPair.getPublic(), signedCSRBytes);
|
||||
|
||||
byte[] rawSignData = getRawSignatureFromDEREncoding(signedCSRBytes);
|
||||
|
||||
jSONObject = new JSONObject();
|
||||
jSONObject.put("iftid",iftid);
|
||||
jSONObject.put("csrsignature",Base64.toBase64String(rawSignData));
|
||||
|
||||
String csrsignatureReqStr = jSONObject.toJSONString();
|
||||
System.out.println(">> CSRSignatureValue Request :" + csrsignatureReqStr);
|
||||
byte[] certificateBytes = HttpFactory.sendPost(csrsignatureReqStr.getBytes(), HttpFactory.REQUESTTYPE.CERTIFICATE);
|
||||
System.out.println(">> CSRSignatureValue Response :" + new String(certificateBytes));
|
||||
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
jSONObject = (JSONObject) jsonParser.parse(new String(certificateBytes));
|
||||
String status = (String) jSONObject.get("status");
|
||||
|
||||
if(!status.equalsIgnoreCase("success")) {
|
||||
throw new Exception((String) jSONObject.get("message"));
|
||||
}
|
||||
|
||||
return (JSONObject) jSONObject.get("data");
|
||||
}
|
||||
|
||||
public static byte[] getRawSignatureFromDEREncoding(byte[] derEncodedSignature) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
byte[] r = new byte[32];
|
||||
byte[] s = new byte[32];
|
||||
|
||||
// Length of r is encoded in the fourth byte
|
||||
int lengthOfR = derEncodedSignature[3];
|
||||
|
||||
// Length of r is encoded in the second byte AFTER r
|
||||
int lengthOfS = derEncodedSignature[lengthOfR + 5];
|
||||
|
||||
// Length of r and s are either 33 bytes (including padding byte 0x00), 32 bytes (normal), or less (leftmost 0x00 bytes were removed)
|
||||
try {
|
||||
if (lengthOfR == 33) System.arraycopy(derEncodedSignature, 5, r, 0, lengthOfR - 1); // skip leftmost padding byte 0x00
|
||||
else if (lengthOfR == 32) System.arraycopy(derEncodedSignature, 4, r, 0, lengthOfR);
|
||||
else System.arraycopy(derEncodedSignature, 4, r, 32 - lengthOfR, lengthOfR); // destPos = number of leftmost 0x00 bytes
|
||||
|
||||
if (lengthOfS == 33) System.arraycopy(derEncodedSignature, lengthOfR + 7, s, 0, lengthOfS - 1); // skip leftmost padding byte 0x00
|
||||
else if (lengthOfS == 32) System.arraycopy(derEncodedSignature, lengthOfR + 6, s, 0, lengthOfS);
|
||||
else System.arraycopy(derEncodedSignature, lengthOfR + 6, s, 32 - lengthOfS, lengthOfS); // destPos = number of leftmost 0x00 bytes
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
baos.write(r);
|
||||
baos.write(s);
|
||||
} catch (IOException e) {
|
||||
}
|
||||
|
||||
byte[] rawRAndS = baos.toByteArray();
|
||||
|
||||
return rawRAndS;
|
||||
}
|
||||
|
||||
public JSONObject verify() throws Exception {
|
||||
jSONObject = new JSONObject();
|
||||
jSONObject.put("iftid",iftid);
|
||||
// jSONObject.put("subjectdn",String.format(ConfigureInfo.revokeDN,pcid));
|
||||
jSONObject.put("pcid",pcid);
|
||||
jSONObject.put("result","fail");
|
||||
|
||||
String verifyResultReqStr = jSONObject.toJSONString();
|
||||
System.out.println(">> VerifyResult Request :" + verifyResultReqStr);
|
||||
byte[] verifyResultRespBytes = HttpFactory.sendPost(verifyResultReqStr.getBytes(), HttpFactory.REQUESTTYPE.VERITYRESULT);
|
||||
System.out.println(">> VerifyResult Response :" + new String(verifyResultRespBytes));
|
||||
|
||||
JSONParser jsonParser = new JSONParser();
|
||||
jSONObject = (JSONObject) jsonParser.parse(new String(verifyResultRespBytes));
|
||||
String status = (String) jSONObject.get("status");
|
||||
|
||||
if(!status.equalsIgnoreCase("success")) {
|
||||
throw new Exception((String) jSONObject.get("message"));
|
||||
}
|
||||
|
||||
return (JSONObject) jSONObject.get("data");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
VpkiApplication app = new VpkiApplication();
|
||||
try {
|
||||
|
||||
app.init();
|
||||
|
||||
JSONObject res1 = app.getCsr();
|
||||
app.hashedCsrStr = (String) res1.get("hashedtbscsr");
|
||||
app.pcid = (String) res1.get("pcid");
|
||||
System.out.println();
|
||||
|
||||
JSONObject res2 = app.getCertificate();
|
||||
System.out.println();
|
||||
|
||||
JSONObject res3 = app.verify();
|
||||
System.out.println();
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
// public static void main(String[] args) {
|
||||
// //Parameter
|
||||
// String macAddress = "abcd0123456";
|
||||
// String wmi = "KMH";
|
||||
// String iftid = "ift01";
|
||||
//
|
||||
// String pubKeyHex = "04BB751403B9E7D6C5132292DBED87F2D739C4811BA5B9ED185D26544C90E4A3CE03308AE2D6744AE83A3762B58BF864BE66373338DC8775F507F96AAE4C487A5C";
|
||||
// String signedDataHex = "B23F130B068AB4FA88057AFA87225A7BC481E33BF91941FB561535D75868A593E7C82B04B50A0E975B6F92659D41B83082981DAE3FB9708560BE91622CFE3076";
|
||||
//
|
||||
// try {
|
||||
// Security.addProvider(new BouncyCastleProvider());
|
||||
// System.out.println("KMH CMS Test Application");
|
||||
//
|
||||
// byte[] pubKeyBytes = hexStringToByteArray(pubKeyHex);
|
||||
// byte[] signBytes = hexStringToByteArray(signedDataHex);
|
||||
// System.out.println("Test Pub Key : " + Base64.toBase64String(pubKeyBytes));
|
||||
// System.out.println("Test signature : " + Base64.toBase64String((signBytes)));
|
||||
//
|
||||
// int EC_POINTSIZE = 32;
|
||||
// byte[] processedXData = new byte[EC_POINTSIZE];
|
||||
// byte[] processedYData = new byte[EC_POINTSIZE];
|
||||
// System.arraycopy(pubKeyBytes, 1, processedXData, 0, EC_POINTSIZE);
|
||||
// System.arraycopy(pubKeyBytes, EC_POINTSIZE + 1, processedYData, 0, EC_POINTSIZE);
|
||||
//
|
||||
// ECPoint pubPoint = new ECPoint(new BigInteger(1, processedXData), new BigInteger(1, processedYData));
|
||||
// AlgorithmParameters params = AlgorithmParameters.getInstance("EC", "BC");
|
||||
// params.init(new ECGenParameterSpec("prime256v1"));
|
||||
// ECParameterSpec ecParameters = params.getParameterSpec(ECParameterSpec.class);
|
||||
// ECPublicKeySpec pubECSpec = new ECPublicKeySpec(pubPoint, ecParameters);
|
||||
// ECPublicKey publicKey = (ECPublicKey) KeyFactory.getInstance("EC", "BC").generatePublic(pubECSpec);
|
||||
//
|
||||
// System.out.println("Test Pub Key : " + Base64.toBase64String(publicKey.getEncoded()));
|
||||
//
|
||||
// //Create Key Pair
|
||||
// KeyPair keyPair = PkiFactory.generateKeyPair(ConfigureInfo.KEY_ALGORITHM);
|
||||
// String b64PubKey = Base64.toBase64String(keyPair.getPublic().getEncoded());
|
||||
// String b64PriKey = Base64.toBase64String(keyPair.getPrivate().getEncoded());
|
||||
//
|
||||
// System.out.println("PublicKey :" + b64PubKey);
|
||||
// System.out.println("PrivateKey :" + b64PriKey);
|
||||
//
|
||||
// //hashed CSR Request
|
||||
// JSONObject jSONObject = new JSONObject();
|
||||
// jSONObject.put("iftid",iftid);
|
||||
// jSONObject.put("macaddr",macAddress);
|
||||
// jSONObject.put("publickey",b64PubKey);
|
||||
// jSONObject.put("wmi",wmi);
|
||||
// String hashedCSRReqStr = jSONObject.toJSONString();
|
||||
// System.out.println("hashedCSR Request :" + hashedCSRReqStr);
|
||||
// byte[] hashedCSRBytes = HttpFactory.sendPost(hashedCSRReqStr.getBytes(), HttpFactory.REQUESTTYPE.HASHEDCSR);
|
||||
// System.out.println("hashedCSR Response :" + new String(hashedCSRBytes));
|
||||
//
|
||||
// JSONParser jsonParser = new JSONParser();
|
||||
// jSONObject = (JSONObject) jsonParser.parse(new String(hashedCSRBytes));
|
||||
// JSONObject jSONObjectData = (JSONObject) jSONObject.get("data");
|
||||
// String hashedCsrStr = (String) jSONObjectData.get("hashedtbscsr");
|
||||
// String pcid = (String) jSONObjectData.get("pcid");
|
||||
//
|
||||
// //Certificate Request
|
||||
// byte[] signedCSRBytes = PkiFactory.signECDSAHashedValue(Base64.decode(hashedCsrStr), keyPair.getPrivate());
|
||||
// jSONObject = new JSONObject();
|
||||
// jSONObject.put("iftid",iftid);
|
||||
// jSONObject.put("csrsignature",Base64.toBase64String(signedCSRBytes));
|
||||
// String csrsignatureReqStr = jSONObject.toJSONString();
|
||||
// System.out.println("CSRSignatureValue Request :" + csrsignatureReqStr);
|
||||
// byte[] certificateBytes = HttpFactory.sendPost(csrsignatureReqStr.getBytes(), HttpFactory.REQUESTTYPE.CERTIFICATE);
|
||||
// System.out.println("CSRSignatureValue Response :" + new String(certificateBytes));
|
||||
//
|
||||
// //VerifyResult Request
|
||||
// jSONObject = new JSONObject();
|
||||
// jSONObject.put("iftid",iftid);
|
||||
// jSONObject.put("subjectdn",String.format(ConfigureInfo.revokeDN,pcid));
|
||||
// jSONObject.put("result","fail");
|
||||
// String verifyResultReqStr = jSONObject.toJSONString();
|
||||
// System.out.println("VerifyResult Request :" + verifyResultReqStr);
|
||||
// byte[] verifyResultRespBytes = HttpFactory.sendPost(verifyResultReqStr.getBytes(), HttpFactory.REQUESTTYPE.VERITYRESULT);
|
||||
// System.out.println("VerifyResult Response :" + new String(verifyResultRespBytes));
|
||||
//
|
||||
// System.out.println("end");
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
|
||||
public static byte[] hexStringToByteArray(String s) {
|
||||
int len = s.length();
|
||||
byte[] data = new byte[len / 2];
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
||||
+ Character.digit(s.charAt(i+1), 16));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
61
Projects/VPKI/Doc/java/vpki/core/HttpFactory.java
Normal file
61
Projects/VPKI/Doc/java/vpki/core/HttpFactory.java
Normal file
@ -0,0 +1,61 @@
|
||||
package vpki.core;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import vpki.ConfigureInfo;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.DataOutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
public class HttpFactory {
|
||||
public enum REQUESTTYPE {
|
||||
HASHEDCSR,
|
||||
CERTIFICATE,
|
||||
VERITYRESULT
|
||||
}
|
||||
|
||||
public static byte[] sendPost(byte[] requestBytes, REQUESTTYPE type) {
|
||||
String connURL = "";
|
||||
String conType = "";
|
||||
|
||||
switch (type) {
|
||||
case HASHEDCSR:
|
||||
connURL = ConfigureInfo.CA_URL + ConfigureInfo.HASHEDCSR;
|
||||
conType = "application/json";
|
||||
break;
|
||||
case CERTIFICATE:
|
||||
connURL = ConfigureInfo.CA_URL + ConfigureInfo.CERTIFICATE;
|
||||
conType = "application/json";
|
||||
break;
|
||||
case VERITYRESULT:
|
||||
connURL = ConfigureInfo.CA_URL + ConfigureInfo.VERITYRESULT;
|
||||
conType = "application/json";
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
URL obj = new URL(connURL);
|
||||
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||
|
||||
// Setting basic post request
|
||||
con.setRequestMethod("POST");
|
||||
con.setRequestProperty("Content-Type", conType);
|
||||
|
||||
// Send post request
|
||||
con.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
|
||||
wr.write(requestBytes);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
|
||||
return IOUtils.toByteArray(con.getInputStream());
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
268
Projects/VPKI/Doc/java/vpki/core/OcspReqClient.java
Normal file
268
Projects/VPKI/Doc/java/vpki/core/OcspReqClient.java
Normal file
@ -0,0 +1,268 @@
|
||||
package vpki.core;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.Socket;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.Security;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.*;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.bouncycastle.asn1.ASN1Encodable;
|
||||
import org.bouncycastle.asn1.ASN1OctetString;
|
||||
import org.bouncycastle.asn1.DEROctetString;
|
||||
import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers;
|
||||
import org.bouncycastle.asn1.x509.CRLReason;
|
||||
import org.bouncycastle.asn1.x509.Extension;
|
||||
import org.bouncycastle.asn1.x509.ExtensionsGenerator;
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
|
||||
import org.bouncycastle.cert.ocsp.BasicOCSPResp;
|
||||
import org.bouncycastle.cert.ocsp.CertificateID;
|
||||
import org.bouncycastle.cert.ocsp.OCSPReq;
|
||||
import org.bouncycastle.cert.ocsp.OCSPReqBuilder;
|
||||
import org.bouncycastle.cert.ocsp.OCSPResp;
|
||||
import org.bouncycastle.cert.ocsp.RevokedStatus;
|
||||
import org.bouncycastle.cert.ocsp.SingleResp;
|
||||
import org.bouncycastle.cert.ocsp.UnknownStatus;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.operator.ContentVerifierProvider;
|
||||
import org.bouncycastle.operator.DigestCalculator;
|
||||
import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
|
||||
import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder;
|
||||
|
||||
class OcspReqCert {
|
||||
X509CertificateHolder caCertHolder; //Issuer Cert
|
||||
X509Certificate userCert; //Valid Target Cert
|
||||
}
|
||||
|
||||
public class OcspReqClient {
|
||||
|
||||
private byte[] sampleNonce; //Nonce
|
||||
private List<OcspReqCert> reqCertList; //Request List
|
||||
private String ocspSvrUrl; //VA URL
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider()); //Load BouncyCastle
|
||||
}
|
||||
|
||||
public OcspReqClient(String ocspSvrUrl) {
|
||||
this.ocspSvrUrl = ocspSvrUrl;
|
||||
this.reqCertList = new ArrayList();
|
||||
}
|
||||
|
||||
// cert binary to X509 Class
|
||||
private static X509Certificate certToValue(byte[] cert) throws CertificateException, NoSuchProviderException {
|
||||
InputStream certInputStream = new ByteArrayInputStream(cert);
|
||||
CertificateFactory certFactory = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
|
||||
return (X509Certificate) certFactory.generateCertificate(certInputStream);
|
||||
}
|
||||
|
||||
private byte[] sendTcp(String ip, int port, byte[] ocspReqBytes) {
|
||||
System.out.println("sendTcp");
|
||||
try {
|
||||
Socket mSocket = new Socket(ip, port);
|
||||
OutputStream os = mSocket.getOutputStream();
|
||||
os.write(ocspReqBytes);
|
||||
os.flush();
|
||||
InputStream is = mSocket.getInputStream();
|
||||
byte[] ocspResponse = new byte[10000];
|
||||
is.read(ocspResponse);
|
||||
mSocket.close();
|
||||
return ocspResponse;
|
||||
} catch (IOException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private byte[] sendGet(byte[] ocspReqBytes) {
|
||||
System.out.println("sendGet");
|
||||
try {
|
||||
//Base64 + URL Encode for HTTP
|
||||
String ocspReq = URLEncoder.encode(Base64.getEncoder().encodeToString(ocspReqBytes), "UTF-8");
|
||||
|
||||
URL url = new URL(this.ocspSvrUrl + "/" + ocspReq);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(3000);
|
||||
conn.setReadTimeout(3000);
|
||||
|
||||
return IOUtils.toByteArray(conn.getInputStream());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] sendPost(byte[] ocspReqBytes) {
|
||||
System.out.println("sendPost");
|
||||
try {
|
||||
|
||||
final String USER_AGENT = "Mozilla/5.0";
|
||||
|
||||
URL obj = new URL(this.ocspSvrUrl);
|
||||
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||
|
||||
// Setting basic post request
|
||||
con.setRequestMethod("POST");
|
||||
con.setRequestProperty("User-Agent", USER_AGENT);
|
||||
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
|
||||
con.setRequestProperty("Content-Type", "application/ocsp-request");
|
||||
|
||||
// Send post request
|
||||
con.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
|
||||
wr.write(ocspReqBytes);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
|
||||
return IOUtils.toByteArray(con.getInputStream());
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void add(String userCert, String issuerCert)
|
||||
throws CertificateException, NoSuchProviderException {
|
||||
OcspReqCert ocspReqCert = new OcspReqCert();
|
||||
|
||||
byte[] caCertificateData = Base64.getDecoder().decode(issuerCert);
|
||||
X509Certificate caCert = certToValue(caCertificateData);
|
||||
|
||||
byte[] userCertificateData = Base64.getDecoder().decode(userCert);
|
||||
|
||||
ocspReqCert.userCert = certToValue(userCertificateData);
|
||||
ocspReqCert.caCertHolder = new JcaX509CertificateHolder(caCert);
|
||||
|
||||
this.reqCertList.add(ocspReqCert);
|
||||
}
|
||||
|
||||
public byte[] buildReq() {
|
||||
try {
|
||||
// Create OCSP Request
|
||||
OCSPReqBuilder reqBuilder = new OCSPReqBuilder();
|
||||
|
||||
for (OcspReqCert reqCert : this.reqCertList) {
|
||||
X509Certificate userCert = reqCert.userCert;
|
||||
|
||||
// Create Request CertID
|
||||
DigestCalculator digestCalculator;
|
||||
digestCalculator = new BcDigestCalculatorProvider().get(CertificateID.HASH_SHA1);
|
||||
|
||||
CertificateID id = new CertificateID(digestCalculator, reqCert.caCertHolder,
|
||||
userCert.getSerialNumber());
|
||||
|
||||
reqBuilder.addRequest(id);
|
||||
}
|
||||
|
||||
// Create nonce Extension
|
||||
sampleNonce = new byte[16];
|
||||
Random rand = new Random();
|
||||
rand.nextBytes(sampleNonce);
|
||||
ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
|
||||
extensionsGenerator.addExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce, false,
|
||||
new DEROctetString(sampleNonce));
|
||||
reqBuilder.setRequestExtensions(extensionsGenerator.generate());
|
||||
|
||||
// Build Request Data
|
||||
OCSPReq ocspReqCli = reqBuilder.build();
|
||||
|
||||
return ocspReqCli.getEncoded();
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String validOcspResponse(byte[] ocspRespBytes) throws Exception {
|
||||
// Process Response
|
||||
OCSPResp ocspRespCli = new OCSPResp(ocspRespBytes);
|
||||
|
||||
if (ocspRespCli.getStatus() == 0) {
|
||||
BasicOCSPResp bRes = (BasicOCSPResp) ocspRespCli.getResponseObject();
|
||||
|
||||
// Check Nonce
|
||||
boolean nounceCheck = false;
|
||||
Extension temp = bRes.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce);
|
||||
ASN1Encodable tmpByte = temp.getParsedValue();
|
||||
byte[] nounce = ((ASN1OctetString) tmpByte).getOctets();
|
||||
for (int u = 0; u < nounce.length; u++) {
|
||||
if (nounce[u] != sampleNonce[u]) {
|
||||
nounceCheck = false;
|
||||
break;
|
||||
}
|
||||
nounceCheck = true;
|
||||
}
|
||||
|
||||
if (nounceCheck) {
|
||||
X509CertificateHolder[] chains = bRes.getCerts();
|
||||
//if (checkValidity(chains)) {
|
||||
JcaContentVerifierProviderBuilder jcaContentVerifierProviderBuilder = new JcaContentVerifierProviderBuilder();
|
||||
jcaContentVerifierProviderBuilder.setProvider(BouncyCastleProvider.PROVIDER_NAME);
|
||||
ContentVerifierProvider contentVerifierProvider = jcaContentVerifierProviderBuilder.build(chains[0]);
|
||||
boolean verify = bRes.isSignatureValid(contentVerifierProvider);
|
||||
if (verify) {
|
||||
SingleResp[] respList = bRes.getResponses();
|
||||
for (SingleResp resp : respList) {
|
||||
CertificateID certID = resp.getCertID();
|
||||
Object status = resp.getCertStatus();
|
||||
Date nextDate = resp.getNextUpdate();
|
||||
Date thisDate = resp.getThisUpdate();
|
||||
if (status instanceof UnknownStatus) {
|
||||
return "Unknown";
|
||||
} else if (status instanceof RevokedStatus) {
|
||||
return "Revoked";
|
||||
} else {
|
||||
return "Good";
|
||||
}
|
||||
}
|
||||
}
|
||||
//} // chain verify
|
||||
} // nounceCheck
|
||||
} // response.getStatus()
|
||||
else {
|
||||
System.out.println(ocspRespCli.getStatus());
|
||||
}
|
||||
return "Error";
|
||||
}
|
||||
|
||||
private boolean checkValidity(X509CertificateHolder[] certs) {
|
||||
int n = certs.length;
|
||||
try {
|
||||
for (int i = 0; i < n - 1; i++) {
|
||||
X509Certificate cert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certs[i]);
|
||||
X509Certificate issuer = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certs[i + 1]);
|
||||
|
||||
if (!cert.getIssuerX500Principal().equals(issuer.getSubjectX500Principal())) {
|
||||
throw new Exception("Certificates do not chain");
|
||||
}
|
||||
cert.verify(issuer.getPublicKey());
|
||||
}
|
||||
X509Certificate last = new JcaX509CertificateConverter().setProvider("BC").getCertificate(certs[n - 1]);
|
||||
// if self-signed, verify the final cert
|
||||
if (last.getIssuerX500Principal().equals(last.getSubjectX500Principal())) {
|
||||
last.verify(last.getPublicKey());
|
||||
} else {
|
||||
throw new Exception("Does not exist root certificate;");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("checkValidity : " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
100
Projects/VPKI/Doc/java/vpki/core/PkiFactory.java
Normal file
100
Projects/VPKI/Doc/java/vpki/core/PkiFactory.java
Normal file
@ -0,0 +1,100 @@
|
||||
package vpki.core;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Integer;
|
||||
import org.bouncycastle.asn1.DERSequenceGenerator;
|
||||
import org.bouncycastle.crypto.digests.SHA256Digest;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.signers.ECDSASigner;
|
||||
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.util.io.pem.PemObject;
|
||||
import org.bouncycastle.util.io.pem.PemReader;
|
||||
import org.bouncycastle.util.io.pem.PemWriter;
|
||||
import vpki.ConfigureInfo;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.util.Base64;
|
||||
|
||||
public class PkiFactory {
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
public static KeyPair generateKeyPair(String algorithm) throws Exception {
|
||||
KeyPairGenerator generator = KeyPairGenerator.getInstance("ECDSA", BouncyCastleProvider.PROVIDER_NAME);
|
||||
ECGenParameterSpec ecsp = new ECGenParameterSpec(algorithm);
|
||||
|
||||
generator.initialize(ecsp, new SecureRandom());
|
||||
|
||||
KeyPair keyPair = generator.generateKeyPair();
|
||||
|
||||
return keyPair;
|
||||
}
|
||||
|
||||
public static String convertPem(String type, byte[] data) throws Exception {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
PemWriter pemWriter = new PemWriter(stringWriter);
|
||||
PemObject pemObject = new PemObject(type, data);
|
||||
pemWriter.writeObject(pemObject);
|
||||
pemWriter.flush();
|
||||
String pemString = stringWriter.toString();
|
||||
return pemString;
|
||||
}
|
||||
|
||||
public static byte[] readPem(String data) throws Exception {
|
||||
PemReader pemReader = new PemReader(new StringReader(data));
|
||||
byte[] contentBytes = pemReader.readPemObject().getContent();
|
||||
return contentBytes;
|
||||
}
|
||||
|
||||
public static String reqOCSPfromPem(byte[] certBytes) throws Exception {
|
||||
OcspReqClient ocspReqClient = new OcspReqClient(ConfigureInfo.OCSP_URL);
|
||||
ocspReqClient.add(Base64.getEncoder().encodeToString(readPem(new String(certBytes))), ConfigureInfo.CA_CERT);
|
||||
byte[] ocspReqBytes = ocspReqClient.buildReq();
|
||||
// Send Post
|
||||
byte[] resPost = ocspReqClient.sendPost(ocspReqBytes);
|
||||
return ocspReqClient.validOcspResponse(resPost);
|
||||
}
|
||||
|
||||
public static byte[] hashSHA256(byte[] data) throws Exception {
|
||||
MessageDigest digest = MessageDigest.getInstance("SHA-256");
|
||||
return digest.digest(data);
|
||||
}
|
||||
|
||||
public static String hashSHA256toString(byte[] data) throws Exception {
|
||||
return Base64.getEncoder().encodeToString(hashSHA256(data));
|
||||
}
|
||||
|
||||
public static byte[] signECDSA(byte[] tbs, PrivateKey privateKey) throws Exception {
|
||||
Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
|
||||
ecdsaSign.initSign(privateKey);
|
||||
ecdsaSign.update(tbs);
|
||||
byte[] signature = ecdsaSign.sign();
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
public static byte[] signECDSAHashedValue(byte[] hashed, PrivateKey privateKey) throws Exception {
|
||||
Signature ecdsaSign = Signature.getInstance("NONEwithECDSA");
|
||||
// Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
|
||||
ecdsaSign.initSign(privateKey);
|
||||
ecdsaSign.update(hashed);
|
||||
byte[] signature = ecdsaSign.sign();
|
||||
|
||||
return signature;
|
||||
}
|
||||
|
||||
public static boolean verifyECDSAHashedValue(byte[] hashed, PublicKey publicKey, byte[] signature) throws Exception {
|
||||
Signature ecdsaSign = Signature.getInstance("NONEwithECDSA");
|
||||
// Signature ecdsaSign = Signature.getInstance("SHA256withECDSA");
|
||||
ecdsaSign.initVerify(publicKey);
|
||||
ecdsaSign.update(hashed);
|
||||
return ecdsaSign.verify(signature);
|
||||
}
|
||||
}
|
||||
201
Projects/VPKI/Doc/java/vpki/core/VPKIFactory.java
Normal file
201
Projects/VPKI/Doc/java/vpki/core/VPKIFactory.java
Normal file
@ -0,0 +1,201 @@
|
||||
package vpki.core;
|
||||
|
||||
import org.bouncycastle.asn1.ASN1Sequence;
|
||||
import org.bouncycastle.asn1.DERBitString;
|
||||
import org.bouncycastle.asn1.DERSet;
|
||||
import org.bouncycastle.asn1.pkcs.CertificationRequest;
|
||||
import org.bouncycastle.asn1.pkcs.CertificationRequestInfo;
|
||||
import org.bouncycastle.asn1.x500.X500Name;
|
||||
import org.bouncycastle.asn1.x500.X500NameBuilder;
|
||||
import org.bouncycastle.asn1.x500.style.BCStyle;
|
||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
|
||||
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
|
||||
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
|
||||
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
|
||||
import vpki.ConfigureInfo;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.KeyPair;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class VPKIFactory {
|
||||
private static HashMap<Character,String> ALPHA;
|
||||
static {
|
||||
ALPHA = new HashMap<Character,String>();
|
||||
ALPHA.put('A',"10");
|
||||
ALPHA.put('B',"11");
|
||||
ALPHA.put('C',"12");
|
||||
ALPHA.put('D',"13");
|
||||
ALPHA.put('E',"14");
|
||||
ALPHA.put('F',"15");
|
||||
ALPHA.put('G',"16");
|
||||
ALPHA.put('H',"17");
|
||||
ALPHA.put('I',"18");
|
||||
ALPHA.put('J',"19");
|
||||
ALPHA.put('K',"20");
|
||||
ALPHA.put('L',"21");
|
||||
ALPHA.put('M',"22");
|
||||
ALPHA.put('N',"23");
|
||||
ALPHA.put('O',"24");
|
||||
ALPHA.put('P',"25");
|
||||
ALPHA.put('Q',"26");
|
||||
ALPHA.put('R',"27");
|
||||
ALPHA.put('S',"28");
|
||||
ALPHA.put('T',"29");
|
||||
ALPHA.put('U',"30");
|
||||
ALPHA.put('V',"31");
|
||||
ALPHA.put('W',"32");
|
||||
ALPHA.put('X',"33");
|
||||
ALPHA.put('Y',"34");
|
||||
ALPHA.put('Z',"35");
|
||||
}
|
||||
|
||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
||||
public static final UUID NAMESPACE_DNS = UUID.fromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8");
|
||||
|
||||
public static String generateRevokeJson(String PCID) {
|
||||
String revokeJson = String.format(ConfigureInfo.revokeDN,PCID);
|
||||
return revokeJson;
|
||||
}
|
||||
|
||||
public static byte[] generateTbsCSR(String PCID, PublicKey publicKey) throws Exception {
|
||||
X500Name subjectRdn = new X500NameBuilder(BCStyle.INSTANCE)
|
||||
.addRDN(BCStyle.DC, "OEM")
|
||||
.addRDN(BCStyle.C, "KR")
|
||||
.addRDN(BCStyle.O, "HKMC")
|
||||
.addRDN(BCStyle.OU, "ECC")
|
||||
.addRDN(BCStyle.OU, "C001")
|
||||
.addRDN(BCStyle.OU, "P001")
|
||||
.addRDN(BCStyle.CN, PCID)
|
||||
.build();
|
||||
|
||||
SubjectPublicKeyInfo subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(ASN1Sequence.getInstance(publicKey.getEncoded()));
|
||||
CertificationRequestInfo certificationRequestInfo = new CertificationRequestInfo(subjectRdn, subjectPublicKeyInfo, new DERSet() );
|
||||
byte[] tbsCSR = certificationRequestInfo.getEncoded();
|
||||
|
||||
return tbsCSR;
|
||||
}
|
||||
|
||||
public static String generateCSR(byte[] tbsCSR, byte[] signedCSR) throws Exception {
|
||||
CertificationRequestInfo certificationRequestInfo = CertificationRequestInfo.getInstance(tbsCSR);
|
||||
CertificationRequest certificationRequest = new CertificationRequest(certificationRequestInfo,
|
||||
new AlgorithmIdentifier (X9ObjectIdentifiers.ecdsa_with_SHA256),
|
||||
new DERBitString(signedCSR) );
|
||||
|
||||
PKCS10CertificationRequest pKCS10CertificationRequest = new PKCS10CertificationRequest(certificationRequest);
|
||||
|
||||
String csrString = PkiFactory.convertPem("CERTIFICATE REQUEST", pKCS10CertificationRequest.getEncoded());
|
||||
return csrString;
|
||||
}
|
||||
|
||||
public static String generateCSR(String PCID, KeyPair keyPair) throws Exception {
|
||||
X500Name subjectRdn = new X500NameBuilder(BCStyle.INSTANCE)
|
||||
.addRDN(BCStyle.DC, "OEM")
|
||||
.addRDN(BCStyle.C, "KR")
|
||||
.addRDN(BCStyle.O, "HKMC")
|
||||
.addRDN(BCStyle.OU, "ECC")
|
||||
.addRDN(BCStyle.OU, "C001")
|
||||
.addRDN(BCStyle.OU, "P001")
|
||||
.addRDN(BCStyle.CN, PCID)
|
||||
.build();
|
||||
|
||||
PKCS10CertificationRequestBuilder pkcs10Builder = new JcaPKCS10CertificationRequestBuilder(subjectRdn, keyPair.getPublic());
|
||||
PKCS10CertificationRequest request = pkcs10Builder.build(
|
||||
new JcaContentSignerBuilder(ConfigureInfo.SIGN_ALGORITHM).setProvider(BouncyCastleProvider.PROVIDER_NAME).build(keyPair.getPrivate()));
|
||||
|
||||
String csrString = PkiFactory.convertPem("CERTIFICATE REQUEST", request.getEncoded());
|
||||
return csrString;
|
||||
}
|
||||
|
||||
public static String generatePCID(String macAddress) {
|
||||
//UUID Version 5
|
||||
String test = getV5Uuid(NAMESPACE_DNS, macAddress).toString().replace("-","");
|
||||
//Base16 to Base32
|
||||
BigInteger num=new BigInteger(test,16);
|
||||
String b32Uuid = num.toString(32).toUpperCase();
|
||||
//OEM Unique ID
|
||||
String oemUniqueID = b32Uuid.substring(b32Uuid.length()-14,b32Uuid.length());
|
||||
//Create PCID
|
||||
String PCID = ConfigureInfo.WMI + oemUniqueID;
|
||||
//Calculate CheckSum
|
||||
PCID += calcCheckSum(PCID.toUpperCase());
|
||||
return PCID;
|
||||
}
|
||||
|
||||
private static String calcCheckSum(String PCID) {
|
||||
String checkSumSource = "";
|
||||
|
||||
for (int i = 0; i < PCID.length(); i++) {
|
||||
if(PCID.charAt(i) >= 'A') {
|
||||
checkSumSource += ALPHA.get(PCID.charAt(i));
|
||||
}else{
|
||||
checkSumSource += PCID.charAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
double checkDigit = 0;
|
||||
for (int i = 0; i < checkSumSource.length(); i++) {
|
||||
int num = Integer.parseInt(checkSumSource.substring(i,i+1));
|
||||
checkDigit += num * Math.pow(2,i);
|
||||
}
|
||||
String checkDigitStr;
|
||||
checkDigitStr = (checkDigit % 11 == 10) ? "X" : String.valueOf((int)(checkDigit % 11));
|
||||
|
||||
return checkDigitStr;
|
||||
}
|
||||
|
||||
public static UUID getV5Uuid(UUID namespace, String name) {
|
||||
return getV5Uuid(namespace, Objects.requireNonNull(name, "name == null").getBytes(UTF8));
|
||||
}
|
||||
|
||||
public static UUID getV5Uuid(UUID namespace, byte[] name) {
|
||||
MessageDigest md;
|
||||
try {
|
||||
md = MessageDigest.getInstance("SHA-1");
|
||||
} catch (NoSuchAlgorithmException nsae) {
|
||||
throw new InternalError("SHA-1 not supported");
|
||||
}
|
||||
md.update(toBytes(Objects.requireNonNull(namespace, "namespace is null")));
|
||||
md.update(Objects.requireNonNull(name, "name is null"));
|
||||
byte[] sha1Bytes = md.digest();
|
||||
sha1Bytes[6] &= 0x0f; /* clear version */
|
||||
sha1Bytes[6] |= 0x50; /* set to version 5 */
|
||||
sha1Bytes[8] &= 0x3f; /* clear variant */
|
||||
sha1Bytes[8] |= 0x80; /* set to IETF variant */
|
||||
return fromBytes(sha1Bytes);
|
||||
}
|
||||
|
||||
private static UUID fromBytes(byte[] data) {
|
||||
// Based on the private UUID(bytes[]) constructor
|
||||
long msb = 0;
|
||||
long lsb = 0;
|
||||
assert data.length >= 16;
|
||||
for (int i = 0; i < 8; i++)
|
||||
msb = (msb << 8) | (data[i] & 0xff);
|
||||
for (int i = 8; i < 16; i++)
|
||||
lsb = (lsb << 8) | (data[i] & 0xff);
|
||||
return new UUID(msb, lsb);
|
||||
}
|
||||
|
||||
private static byte[] toBytes(UUID uuid) {
|
||||
// inverted logic of fromBytes()
|
||||
byte[] out = new byte[16];
|
||||
long msb = uuid.getMostSignificantBits();
|
||||
long lsb = uuid.getLeastSignificantBits();
|
||||
for (int i = 0; i < 8; i++)
|
||||
out[i] = (byte) ((msb >> ((7 - i) * 8)) & 0xff);
|
||||
for (int i = 8; i < 16; i++)
|
||||
out[i] = (byte) ((lsb >> ((15 - i) * 8)) & 0xff);
|
||||
return out;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user