From 7b0cc1cafb06fd2fbfdf0e6ea3a0015513c28d9d Mon Sep 17 00:00:00 2001 From: zhanglin33 Date: Tue, 14 May 2019 16:30:29 +0800 Subject: [PATCH] add CSRBuilder and its junitTest --- .../crypto/utils/classic/RSAUtils.java | 2 +- .../com/jd/blockchain/crypto/CSRBuilder.java | 121 +++++++++- .../jd/blockchain/crypto/CSRBuilderTest.java | 214 +++++++----------- 3 files changed, 195 insertions(+), 142 deletions(-) diff --git a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java index bc1e5bdc..f17dcdf2 100644 --- a/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java +++ b/source/crypto/crypto-classic/src/main/java/com/jd/blockchain/crypto/utils/classic/RSAUtils.java @@ -83,7 +83,7 @@ public class RSAUtils { * @return key pair */ public static AsymmetricCipherKeyPair generateKeyPair_shortExp(){ - return generateKeyPair(new SecureRandom()); + return generateKeyPair_shortExp(new SecureRandom()); } public static AsymmetricCipherKeyPair generateKeyPair_shortExp(SecureRandom random){ diff --git a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java index 3cef8326..7ec35785 100644 --- a/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java +++ b/source/crypto/crypto-pki/src/main/java/com/jd/blockchain/crypto/CSRBuilder.java @@ -1,6 +1,25 @@ 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.X500NameBuilder; +import org.bouncycastle.asn1.x500.style.BCStrictStyle; +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.spec.ECNamedCurveGenParameterSpec; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; +import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; +import org.bouncycastle.util.encoders.Base64; + + +import java.io.IOException; +import java.security.*; /** * @author zhanglin33 @@ -10,20 +29,98 @@ import org.bouncycastle.crypto.AsymmetricCipherKeyPair; */ public class CSRBuilder { - private String C; - private String ST; - private String L; - private String O; - private String OU; - private String CN; - private String E; + private String BC = BouncyCastleProvider.PROVIDER_NAME; + + private PublicKey pubKey; + private PrivateKey privKey; + + private String algoName; + + public void init() { + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + algoName = "SHA1withRSA"; + KeyPairGenerator generator; + try { + generator = KeyPairGenerator.getInstance("RSA", BC); + generator.initialize(2048); + KeyPair keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); + } catch (NoSuchAlgorithmException | NoSuchProviderException e) { + throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); + } + } + + public void init(String algoName, int KeyLength) { + + Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); + this.algoName = algoName; + + KeyPairGenerator generator; + KeyPair keyPair; + String[] hashAndSignature = algoName.split("with"); + + try { + switch (hashAndSignature[1]) { + case "RSA": { + generator = KeyPairGenerator.getInstance("RSA", BC); + generator.initialize(KeyLength); + keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); + } + + case "SM2": { + generator = KeyPairGenerator.getInstance("EC", BC); + generator.initialize(new ECNamedCurveGenParameterSpec("sm2p256v1")); + keyPair = generator.generateKeyPair(); + pubKey = keyPair.getPublic(); + privKey = keyPair.getPrivate(); + } + + default: throw new CryptoException("Unsupported key algorithm[" + algoName + "] in CSR!"); + } + } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) { + throw new com.jd.blockchain.crypto.CryptoException(e.getMessage(), e); + } + } + + public String buildRequest(String countryName, String stateName, String cityName, + String organizationName, String departmentName, String domainName, + String emailName) { + + String result = null; + X500NameBuilder nameBuilder = new X500NameBuilder(BCStrictStyle.INSTANCE); + + nameBuilder.addRDN(BCStyle.C, countryName); // a country name, and China is short as CN + nameBuilder.addRDN(BCStyle.ST, stateName); // a state or province name + nameBuilder.addRDN(BCStyle.L, cityName); // a city name + nameBuilder.addRDN(BCStyle.O, organizationName); // an organization or corporation name + nameBuilder.addRDN(BCStyle.OU, departmentName); // a division of your organization name + nameBuilder.addRDN(BCStyle.CN, domainName); // a fully qualified domain name + nameBuilder.addRDN(BCStyle.E, emailName); // an email address + + try { + X500Name x500Name = nameBuilder.build(); + + PKCS10CertificationRequestBuilder requestBuilder + = new JcaPKCS10CertificationRequestBuilder(x500Name, pubKey); + PKCS10CertificationRequest request + = requestBuilder.build(new JcaContentSignerBuilder(algoName).setProvider(BC).build(privKey)); + byte[] csrBytes = request.getEncoded(); + result = Base64.toBase64String(csrBytes); + } catch (OperatorCreationException | IOException e) { + e.printStackTrace(); + } + + return result; + } - public AsymmetricCipherKeyPair init() { - return null; + public PublicKey getPubKey() { + return pubKey; } - public String buildRequest(String keyName, AsymmetricCipherKeyPair keyPair, String algoName, - String[] applicantInfo) { - return null; + public PrivateKey getPrivKey() { + return privKey; } } diff --git a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java index 42ecff9e..b61f3ca1 100644 --- a/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java +++ b/source/crypto/crypto-pki/src/test/java/com/jd/blockchain/crypto/CSRBuilderTest.java @@ -1,32 +1,18 @@ package com.jd.blockchain.crypto; -import com.jd.blockchain.crypto.utils.classic.RSAUtils; -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x500.X500NameBuilder; -import org.bouncycastle.asn1.x500.style.BCStrictStyle; +import org.bouncycastle.asn1.ASN1Encoding; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.pkcs.CertificationRequestInfo; +import org.bouncycastle.asn1.x500.RDN; import org.bouncycastle.asn1.x500.style.BCStyle; -import org.bouncycastle.asn1.x500.style.RFC4519Style; -import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; -import org.bouncycastle.crypto.AsymmetricCipherKeyPair; -import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; -import org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder; import org.bouncycastle.pkcs.PKCS10CertificationRequest; -import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder; -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequest; -import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; -import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Base64; import org.junit.Test; -import sun.security.rsa.RSAPublicKeyImpl; import java.io.IOException; import java.security.*; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; /** * @author zhanglin33 @@ -35,127 +21,97 @@ import static org.junit.Assert.fail; * @date 2019-05-10, 17:22 */ public class CSRBuilderTest { - public static String genCSR(String subject, String alg, String provider) { - String signalg = ""; - int alglength = 0; - String keyAlg = ""; - if (alg.toUpperCase().equals("RSA1024")) { - signalg = "SHA1WithRSA"; - alglength = 1024; - keyAlg = "RSA"; - } else if (alg.toUpperCase().equals("RSA2048")) { - signalg = "SHA1WithRSA"; - alglength = 2048; - keyAlg = "RSA"; - } else if (alg.toUpperCase().equals("SM2")) { - signalg = "SM3withSM2"; - alglength = 256; - keyAlg = "SM2"; - } - KeyPairGenerator keyGen; - PKCS10CertificationRequestBuilder builder; - - try { - keyGen = KeyPairGenerator.getInstance(keyAlg); - keyGen.initialize(alglength); - KeyPair kp = keyGen.generateKeyPair(); - - - builder = new PKCS10CertificationRequestBuilder(new X500Name(subject), SubjectPublicKeyInfo.getInstance(kp.getPublic().getEncoded())); - JcaContentSignerBuilder jcaContentSignerBuilder = new JcaContentSignerBuilder(signalg); - jcaContentSignerBuilder.setProvider(provider); - ContentSigner contentSigner = jcaContentSignerBuilder.build(kp.getPrivate()); - builder.build(contentSigner); - return builder.toString(); - } catch (OperatorCreationException | NoSuchAlgorithmException e) { - e.printStackTrace(); - } - return null; - } - - @Test - public void csrTest() throws Exception{ - - Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); - - - String keyName = "RSA"; - String sigName = "SHA1withRSA"; - - String BC = BouncyCastleProvider.PROVIDER_NAME; - KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyName, BC); - - kpg.initialize(2048); - - KeyPair kp = kpg.generateKeyPair(); -// AsymmetricCipherKeyPair keyPair = RSAUtils.generateKeyPair(); - - - X500NameBuilder builder = new X500NameBuilder(BCStrictStyle.INSTANCE); - - builder.addRDN(BCStyle.C,"CN"); // a country name, and China is short as CN - builder.addRDN(BCStyle.ST, "Beijing"); // a state or province name - builder.addRDN(BCStyle.L, "Beijing"); // a city name - builder.addRDN(BCStyle.O, "JD.com"); // an organization or corporation name - builder.addRDN(BCStyle.OU, "Blockchain Department"); // a division of your organization name - builder.addRDN(BCStyle.CN, "ledger.jd.com"); // a fully qualified domain name - builder.addRDN(BCStyle.EmailAddress, "zhanglin33@jd.com"); // an email address - - X500Name x500Name = builder.build(); - - PKCS10CertificationRequestBuilder requestBuilder = new JcaPKCS10CertificationRequestBuilder(x500Name, kp.getPublic()); - -// PKCS10CertificationRequest req = requestBuilder.build(new JcaContentSignerBuilder(sigName).setProvider(sigName).build(kp.getPrivate())); - PKCS10CertificationRequest req = requestBuilder.build(new JcaContentSignerBuilder(sigName).setProvider(BC).build(kp.getPrivate())); - - - byte[] csrBytes = req.getEncoded(); - String result = Base64.toBase64String(csrBytes); - System.out.println(result); - - } @Test - public void csr2Test() throws Exception { - Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); - generationTest(512, "RSA", "SHA1withRSA", "BC"); - } - - private void generationTest(int keySize, String keyName, String sigName, String provider) - throws Exception { - KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyName, "BC"); - - kpg.initialize(keySize); - - KeyPair kp = kpg.generateKeyPair(); + public void defaultCSRTest(){ + String countryName = "CN"; + String stateName = "Beijing"; + String cityName = "Beijing"; + String organizationName = "JD.com"; + String departmentName = "Blockchain Department"; + String domainName = "ledger.jd.com"; + String emailName = "zhanglin33@jd.com"; - X500NameBuilder x500NameBld = new X500NameBuilder(BCStyle.INSTANCE); + CSRBuilder builder = new CSRBuilder(); - x500NameBld.addRDN(BCStyle.C, "AU"); - x500NameBld.addRDN(BCStyle.O, "The Legion of the Bouncy Castle"); - x500NameBld.addRDN(BCStyle.L, "Melbourne"); - x500NameBld.addRDN(BCStyle.ST, "Victoria"); + builder.init(); + String csr = builder.buildRequest(countryName,stateName,cityName, + organizationName,departmentName,domainName, + emailName); + System.out.println(csr); - x500NameBld.addRDN(BCStyle.EmailAddress, "feedback-crypto@bouncycastle.org"); + PublicKey pubKey = builder.getPubKey(); + PrivateKey privKey = builder.getPrivKey(); - X500Name subject = x500NameBld.build(); - - PKCS10CertificationRequestBuilder requestBuilder = new JcaPKCS10CertificationRequestBuilder(subject, kp.getPublic()); - BCRSAPublicKey pubKey = (BCRSAPublicKey) kp.getPublic(); - System.out.println(pubKey.getModulus().bitLength()); - - PKCS10CertificationRequest req1 = requestBuilder.build(new JcaContentSignerBuilder(sigName).setProvider(provider).build(kp.getPrivate())); - - JcaPKCS10CertificationRequest req2 = new JcaPKCS10CertificationRequest(req1.getEncoded()).setProvider(provider); + byte[] crsBytes = Base64.decode(csr); + PKCS10CertificationRequest request = null; + try { + request = new PKCS10CertificationRequest(crsBytes); + } catch (IOException e) { + e.printStackTrace(); + } + assertNotNull(request); + assertEquals("1.2.840.113549.1.1.5",request.getSignatureAlgorithm().getAlgorithm().getId()); + byte[] pubKeyBytes = new byte[0]; + try { + pubKeyBytes = request.getSubjectPublicKeyInfo().getEncoded(); + } catch (IOException e) { + e.printStackTrace(); + } + assertArrayEquals(pubKeyBytes,pubKey.getEncoded()); + + RDN[] rdns = request.getSubject().getRDNs(); + assertEquals(BCStyle.C, rdns[0].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.ST, rdns[1].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.L, rdns[2].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.O, rdns[3].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.OU, rdns[4].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.CN, rdns[5].getFirst().getType().toASN1Primitive()); + assertEquals(BCStyle.E, rdns[6].getFirst().getType().toASN1Primitive()); + + assertEquals("CN", rdns[0].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[1].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Beijing", rdns[2].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("JD.com", rdns[3].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("Blockchain Department", rdns[4].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("ledger.jd.com", rdns[5].getFirst().getValue().toASN1Primitive().toString()); + assertEquals("zhanglin33@jd.com", rdns[6].getFirst().getValue().toASN1Primitive().toString()); + + byte[] signature = request.getSignature(); + + CertificationRequestInfo requestInfo = new CertificationRequestInfo(request.getSubject(),request.getSubjectPublicKeyInfo(),new DERSet()); + byte[] message = new byte[0]; + try { + message = requestInfo.getEncoded(ASN1Encoding.DER); + } catch (IOException e) { + e.printStackTrace(); + } - if (!req2.isSignatureValid(new JcaContentVerifierProviderBuilder().setProvider(provider).build(kp.getPublic()))) { - fail(sigName + ": Failed verify check."); + Signature signer; + byte[] result = new byte[0]; + try { + signer = Signature.getInstance("SHA1withRSA"); + signer.initSign(privKey); + signer.update(message); + result = signer.sign(); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); } + assertArrayEquals(result,signature); - if (!Arrays.areEqual(req2.getPublicKey().getEncoded(), req1.getSubjectPublicKeyInfo().getEncoded())) { - fail(keyName + ": Failed public key check."); + Signature verifier; + boolean isValid = false; + try { + verifier = Signature.getInstance("SHA1withRSA"); + verifier.initVerify(pubKey); + verifier.update(message); + isValid = verifier.verify(signature); + } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { + e.printStackTrace(); } + assertTrue(isValid); } + }