@@ -1,13 +1,9 @@ | |||||
package com.jd.blockchain.crypto; | package com.jd.blockchain.crypto; | ||||
import com.jd.blockchain.crypto.utils.classic.RSAUtils; | |||||
import org.bouncycastle.asn1.x500.RDN; | |||||
import org.bouncycastle.asn1.x500.X500Name; | import org.bouncycastle.asn1.x500.X500Name; | ||||
import org.bouncycastle.asn1.x500.X500NameBuilder; | import org.bouncycastle.asn1.x500.X500NameBuilder; | ||||
import org.bouncycastle.asn1.x500.style.BCStrictStyle; | import org.bouncycastle.asn1.x500.style.BCStrictStyle; | ||||
import org.bouncycastle.asn1.x500.style.BCStyle; | import org.bouncycastle.asn1.x500.style.BCStyle; | ||||
import org.bouncycastle.crypto.AsymmetricCipherKeyPair; | |||||
import org.bouncycastle.crypto.params.AsymmetricKeyParameter; | |||||
import org.bouncycastle.jce.provider.BouncyCastleProvider; | import org.bouncycastle.jce.provider.BouncyCastleProvider; | ||||
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec; | import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec; | ||||
import org.bouncycastle.operator.OperatorCreationException; | import org.bouncycastle.operator.OperatorCreationException; | ||||
@@ -47,7 +43,7 @@ public class CSRBuilder { | |||||
pubKey = keyPair.getPublic(); | pubKey = keyPair.getPublic(); | ||||
privKey = keyPair.getPrivate(); | privKey = keyPair.getPrivate(); | ||||
} catch (NoSuchAlgorithmException | NoSuchProviderException e) { | } catch (NoSuchAlgorithmException | NoSuchProviderException e) { | ||||
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); | |||||
throw new CryptoException(e.getMessage(), e); | |||||
} | } | ||||
} | } | ||||
@@ -81,7 +77,7 @@ public class CSRBuilder { | |||||
default: throw new CryptoException("Unsupported key algorithm[" + algoName + "] in CSR!"); | default: throw new CryptoException("Unsupported key algorithm[" + algoName + "] in CSR!"); | ||||
} | } | ||||
} catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { | } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { | ||||
throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); | |||||
throw new CryptoException(e.getMessage(), e); | |||||
} | } | ||||
} | } | ||||
@@ -110,7 +106,7 @@ public class CSRBuilder { | |||||
byte[] csrBytes = request.getEncoded(); | byte[] csrBytes = request.getEncoded(); | ||||
result = Base64.toBase64String(csrBytes); | result = Base64.toBase64String(csrBytes); | ||||
} catch (OperatorCreationException | IOException e) { | } catch (OperatorCreationException | IOException e) { | ||||
e.printStackTrace(); | |||||
throw new CryptoException(e.getMessage(), e); | |||||
} | } | ||||
return result; | return result; | ||||
@@ -123,4 +119,12 @@ public class CSRBuilder { | |||||
public PrivateKey getPrivKey() { | public PrivateKey getPrivKey() { | ||||
return privKey; | return privKey; | ||||
} | } | ||||
public byte[] getPubKeyBytes() { | |||||
return pubKey.getEncoded(); | |||||
} | |||||
public byte[] getPrivKeyBytes() { | |||||
return privKey.getEncoded(); | |||||
} | |||||
} | } |
@@ -1,5 +1,17 @@ | |||||
package com.jd.blockchain.crypto; | package com.jd.blockchain.crypto; | ||||
import org.bouncycastle.jce.provider.BouncyCastleProvider; | |||||
import org.bouncycastle.util.encoders.Base64; | |||||
import org.bouncycastle.util.io.pem.PemReader; | |||||
import javax.security.auth.x500.X500Principal; | |||||
import java.io.ByteArrayInputStream; | |||||
import java.io.IOException; | |||||
import java.io.StringReader; | |||||
import java.security.*; | |||||
import java.security.cert.*; | |||||
import java.util.Date; | |||||
/** | /** | ||||
* @author zhanglin33 | * @author zhanglin33 | ||||
* @title: CertParser | * @title: CertParser | ||||
@@ -7,4 +19,112 @@ package com.jd.blockchain.crypto; | |||||
* @date 2019-05-10, 15:17 | * @date 2019-05-10, 15:17 | ||||
*/ | */ | ||||
public class CertParser { | public class CertParser { | ||||
private PublicKey pubKey; | |||||
private String sigAlgName; | |||||
private String userName; | |||||
private String issuerName; | |||||
private Date startTime; | |||||
private Date endTime; | |||||
public void parse(String userCertificate, String issuerCertificate) { | |||||
X509Certificate issuerCert = parseWithoutValidationProcess(issuerCertificate); | |||||
// ensure that the certificate is within the validity period | |||||
try { | |||||
issuerCert.checkValidity(); | |||||
} catch (CertificateExpiredException | CertificateNotYetValidException e) { | |||||
e.printStackTrace(); | |||||
} | |||||
PublicKey issuerPubKey = issuerCert.getPublicKey(); | |||||
X500Principal issuerPrincipal = issuerCert.getSubjectX500Principal(); | |||||
X509Certificate userCert = parseWithoutValidationProcess(userCertificate); | |||||
// check consistency between issuer's names in userCertificate and issuerCertificate | |||||
if (!userCert.getIssuerX500Principal().equals(issuerPrincipal)) { | |||||
throw new CryptoException("Issuer in the targeted certificate is not " + | |||||
"compliance with the parent certificate!"); | |||||
} | |||||
try { | |||||
userCert.checkValidity(); | |||||
} catch (CertificateExpiredException | CertificateNotYetValidException e) { | |||||
throw new CryptoException(e.getMessage(), e); | |||||
} | |||||
// verify the signature in certificate with issuer's public key | |||||
try { | |||||
userCert.verify(issuerPubKey); | |||||
} catch (CertificateException | NoSuchAlgorithmException | |||||
| InvalidKeyException | NoSuchProviderException | SignatureException e) { | |||||
throw new CryptoException(e.getMessage(), e); | |||||
} | |||||
startTime = userCert.getNotBefore(); | |||||
endTime = userCert.getNotAfter(); | |||||
pubKey = userCert.getPublicKey(); | |||||
sigAlgName = userCert.getSigAlgName(); | |||||
issuerName = userCert.getIssuerX500Principal().getName(); | |||||
userName = userCert.getSubjectX500Principal().getName(); | |||||
} | |||||
// certificate string in Base64 format | |||||
public X509Certificate parseWithoutValidationProcess(String certificate) { | |||||
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); | |||||
byte[] certificateBytes; | |||||
String BEGIN = "-----BEGIN CERTIFICATE-----"; | |||||
String END = "-----END CERTIFICATE-----"; | |||||
if (!certificate.startsWith(BEGIN)) { | |||||
certificate = certificate.replaceAll("\\n", ""); | |||||
certificate = certificate.replaceAll(END, ""); | |||||
certificateBytes = Base64.decode(certificate); | |||||
} else { | |||||
try { | |||||
certificateBytes = new PemReader(new StringReader(certificate)).readPemObject().getContent(); | |||||
} catch (IOException e) { | |||||
throw new CryptoException(e.getMessage(), e); | |||||
} | |||||
} | |||||
ByteArrayInputStream bytesIn = new ByteArrayInputStream(certificateBytes); | |||||
CertificateFactory factory; | |||||
X509Certificate cert; | |||||
try { | |||||
factory = CertificateFactory.getInstance("X509", BouncyCastleProvider.PROVIDER_NAME); | |||||
cert = (X509Certificate) factory.generateCertificate(bytesIn); | |||||
} catch (CertificateException | NoSuchProviderException e) { | |||||
throw new CryptoException(e.getMessage(), e); | |||||
} | |||||
return cert; | |||||
} | |||||
public PublicKey getPubKey() { | |||||
return pubKey; | |||||
} | |||||
public String getSigAlgName() { | |||||
return sigAlgName; | |||||
} | |||||
public String getUserName() { | |||||
return userName; | |||||
} | |||||
public String getIssuerName() { | |||||
return issuerName; | |||||
} | |||||
public Date getStartTime() { | |||||
return startTime; | |||||
} | |||||
public Date getEndTime() { | |||||
return endTime; | |||||
} | |||||
} | } |
@@ -112,6 +112,4 @@ public class CSRBuilderTest { | |||||
} | } | ||||
assertTrue(isValid); | assertTrue(isValid); | ||||
} | } | ||||
} | } |
@@ -1,5 +1,9 @@ | |||||
package com.jd.blockchain.crypto; | package com.jd.blockchain.crypto; | ||||
import org.junit.Test; | |||||
import static org.junit.Assert.assertEquals; | |||||
/** | /** | ||||
* @author zhanglin33 | * @author zhanglin33 | ||||
* @title: CertParserTest | * @title: CertParserTest | ||||
@@ -7,4 +11,38 @@ package com.jd.blockchain.crypto; | |||||
* @date 2019-05-13, 10:05 | * @date 2019-05-13, 10:05 | ||||
*/ | */ | ||||
public class CertParserTest { | public class CertParserTest { | ||||
@Test | |||||
public void parseTest() { | |||||
CertParser parser = new CertParser(); | |||||
String issuerCert = | |||||
"-----BEGIN CERTIFICATE-----\n" + | |||||
"MIIDzzCCAregAwIBAgIKUalCR1Mt5ZSK8jANBgkqhkiG9w0BAQUFADBZMQswCQYD\n" + | |||||
"VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g\n" + | |||||
"QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODI5MDU1\n" + | |||||
"NDM2WhcNMzIwODI0MDU1NDM2WjBZMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp\n" + | |||||
"bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDEw9D\n" + | |||||
"RkNBIFRFU1QgT0NBMTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8\n" + | |||||
"jn0n8Fp6hcRdACdn1+Y6GAkC6KGgNdKyHPrmsdmhCjnd/i4qUFwnG8cp3D4lFw1G\n" + | |||||
"jmjSO5yVYbik/NbS6lbNpRgTK3fDfMFvLJpRIC+IFhG9SdAC2hwjsH9qTpL9cK2M\n" + | |||||
"bSdrC6pBdDgnbzaM9AGBF4Y6vXhj5nah4ZMsBvDp19LzXjlGuTPLuAgv9ZlWknsd\n" + | |||||
"RN70PIAmvomd10uqX4GIJ4Jq/FdKXOLZ2DNK/NhRyN6Yq71L3ham6tutXeZow5t5\n" + | |||||
"0254AnUlo1u6SeH9F8itER653o/oMLFwp+63qXAcqrHUlOQPX+JI8fkumSqZ4F2F\n" + | |||||
"t/HfVMnqdtFNCnh5+eIBAgMBAAGjgZgwgZUwHwYDVR0jBBgwFoAUdN7FjQp9EBqq\n" + | |||||
"aYNbTSHOhpvMcTgwDAYDVR0TBAUwAwEB/zA4BgNVHR8EMTAvMC2gK6AphidodHRw\n" + | |||||
"Oi8vMjEwLjc0LjQyLjMvdGVzdHJjYS9SU0EvY3JsMS5jcmwwCwYDVR0PBAQDAgEG\n" + | |||||
"MB0GA1UdDgQWBBT8C7xEmg4xoYOpgYcnHgVCxr9W+DANBgkqhkiG9w0BAQUFAAOC\n" + | |||||
"AQEAb7W0K9fZPA+JPw6lRiMDaUJ0oh052yEXreMBfoPulxkBj439qombDiFggRLc\n" + | |||||
"3g8wIEKzMOzOKXTWtnzYwN3y/JQSuJb/M1QqOEEM2PZwCxI4AkBuH6jg03RjlkHg\n" + | |||||
"/kTtuIFp9ItBCC2/KkKlp0ENfn4XgVg2KtAjZ7lpyVU0LPnhEqqUVY/xthjlCSa7\n" + | |||||
"/XHNStRxsfCTIBUWJ8n2FZyQhfV/UkMNHDBIiJR0v6C4Ai0/290WvbPEIAq+03Si\n" + | |||||
"fsHzBeA0C8lP5VzfAr6wWePaZMCpStpLaoXNcAqReKxQllElOqAhRxC5VKH+rnIQ\n" + | |||||
"OMRZvB7FRyE9IfwKApngcZbA5g==\n" + | |||||
"-----END CERTIFICATE-----"; | |||||
String userCert = "MIIEQDCCAyigAwIBAgIFICdVYzEwDQYJKoZIhvcNAQEFBQAwWTELMAkGA1UEBhMCQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEYMBYGA1UEAxMPQ0ZDQSBURVNUIE9DQTExMB4XDTE5MDUxMDExMjAyNFoXDTIxMDUxMDExMjAyNFowcjELMAkGA1UEBhMCQ04xGDAWBgNVBAoTD0NGQ0EgVEVTVCBPQ0ExMTERMA8GA1UECxMITG9jYWwgUkExFTATBgNVBAsTDEluZGl2aWR1YWwtMTEfMB0GA1UEAxQWMDUxQGFhYWFhQFpIMDkzNTgwMjhAMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJx3F2WD1dJPzK/nRHO7d1TJ1hTjzGTmv0PQ7ECsJAh3U3BtnGTpCB+b4+JMI4LO8nHkKIBQ3P9XnF+Bf1iXdWNAQ4aWCxa2nV7lCp4w0GliPu/EMgIfmsSDUtgqbM3cr8sR8r9m1xG3gt2TIQJ+jT7sAiguU/kyNzpjaccOUIgUFa8IDFq9UeB76MXtCuhlERRZQCl47e+9w7ZoxmE7e6IZORxPp7rQWVBHlR9ntWjJfNDTm3gMP5ehP+yIZnKx1LudxkBLQxpMmspzOyH1zqx5nkKe49AfWWpDxxRvYkriyYC3aE81qLsU/bhLwNEKOju7BGDF/mhJLZUedojM0gMCAwEAAaOB9TCB8jAfBgNVHSMEGDAWgBT8C7xEmg4xoYOpgYcnHgVCxr9W+DBIBgNVHSAEQTA/MD0GCGCBHIbvKgECMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2ZjYS5jb20uY24vdXMvdXMtMTUuaHRtMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly8yMTAuNzQuNDIuMy9PQ0ExMS9SU0EvY3JsMjU2OTMuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU5oKGaQs7Jt5Gfbt1XhFTWAySEKswHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAlmPRaImZV51iKjtpMKuyLMw7dX8L0lY3tl+pVZZSxHuwsN4GCCtV0Ej50up+/6EbfL4NUTiuHVAjCroKKvb+94CrdEwdnQGM5IbGSjT78nQpeASXbIWuUwA+ImjvZOzvq/0b56AzonNzBxOMGko/bj5smM6X8jrgJ0NQppo2KNSVNC4JbuoNWI4FM94SE4DUi9H7EYl4JdOtDaDtCsq49o/A1CZyYrmoOPCgxpQQXmuB3lGq/jyoOlW2aW8uee/hYG1JJcSHLBjF0WBwdxssgbBotA5f1PebiIMSbFgjk57bd4M80hhU/rI4Hkn9pcp5R7NsX95TtyDIg90LboBnW"; | |||||
parser.parse(userCert, issuerCert); | |||||
assertEquals("SHA1WITHRSA",parser.getSigAlgName()); | |||||
} | |||||
} | } |