【问题标题】:Sign CSR with BouncyCastle与 BouncyCastle 签署 CSR
【发布时间】:2016-05-30 09:29:31
【问题描述】:

过去几天我一直在寻找解决问题的方法,但找不到任何东西。我的代码中遗漏了一些东西,但我不知道是什么:(不知何故,当我签署我的 PKCS#10 时,链条断了。

基本上我有一个服务器和一个客户端。我想让客户端向服务器发送 CSR,服务器对其进行签名以便他们可以通信。现在我确实为客户端设置了一个带有 BouncyCastle 的 PKCS#12,并且我确实为服务器设置了一个 RootCertificate(再次使用 BouncyCastle,据我了解,这只是一个带有扩展名的 PKCS#12 以便能够签署证书) 在代码中它看起来像这样:

Provider BC = new BouncyCastleProvider();
Security.addProvider(BC);
//create KeyPair
KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", "BC");
kpGen.initialize(2048, new SecureRandom());
pair = kpGen.generateKeyPair();
//building groundbase for certificate
X500NameBuilder builder = new X500NameBuilder(BCStyle.INSTANCE);
builder.addRDN(BCStyle.CN, commonName);
builder.addRDN(BCStyle.OU, organizationalUnit);
builder.addRDN(BCStyle.O, organization);
builder.addRDN(BCStyle.L, city);
builder.addRDN(BCStyle.ST, state);
builder.addRDN(BCStyle.C, country);
Date notBefore = new Date(System.currentTimeMillis() - 1000L * 60 * 60 * 24); //Yesterday
Date notAfter = new Date(System.currentTimeMillis() +  1000L * 365L * 24L * 60L * 60L); //in a year
BigInteger serial = BigInteger.valueOf(new SecureRandom().nextLong());
//creating a self-signed certificate from information in builder
X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(builder.build(),
serial, notBefore, notAfter, builder.build(), pair.getPublic());

//The next line will make the difference between a Certificate and a Ca Certificate
certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(true));

ContentSigner sigGen = new JcaContentSignerBuilder(").setProvider(BC).build(pair.getPrivate());
X509Certificate cert = new JcaX509CertificateConverter().setProvider(BC).getCertificate(certGen.build(sigGen));

现在我为客户端创建一个 CSR(客户端密钥库在第一个位置有刚刚创建的 PKCS#12):

String alias = keystore.aliases().nextElement();
X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);
X500Name x500name = new JcaX509CertificateHolder(cert).getSubject();
//builder for the PKCS10
PKCS10CertificationRequestBuilder requestBuilder = new JcaPKCS10CertificationRequestBuilder(x500name, cert.getPublicKey());
//algorithm identifier
DefaultSignatureAlgorithmIdentifierFinder sigAlgFinder = new DefaultSignatureAlgorithmIdentifierFinder();
DefaultDigestAlgorithmIdentifierFinder digAlgFinder = new DefaultDigestAlgorithmIdentifierFinder();
AlgorithmIdentifier sigAlgId = sigAlgFinder.find("SHA512WithRSA");
digAlgFinder.find(sigAlgId);
//content Signer
JcaContentSignerBuilder contentSignerBuilder = new JcaContentSignerBuilder("SHA512WithRSA");
//and build the Cert
ContentSigner signer = contentSignerBuilder.build((PrivateKey) keystore.getKey(alias, password));
PKCS10CertificationRequest req = requestBuilder.build(signer);
JcaPKCS10CertificationRequest req2 = new JcaPKCS10CertificationRequest(req.getEncoded()).setProvider("BC");

我通过网络发送这个 JcaPKCS10CertificationRequest 编码。服务器得到它并创建他的 CA 证书,现在必须签署 PKCS#10 但我在这里遗漏了一些东西,因为他不包括链。他正在创建的证书包含有关颁发者和 BasicConstraints 的信息,但证书路径仅包括客户端证书而不包括服务器证书,因此它不可信,因为链已断开。

这就是我要做的(服务器密钥库在位置 0 有 CA 证书,CSR 是 JcaPKCS10CertificationRequest):

String alias = keystore.aliases().nextElement();
// PKCS#12 Root Certificate
X509Certificate cert = (X509Certificate) keystore.getCertificate(alias);
// generated Serial
BigInteger serial = BigInteger.valueOf(new SecureRandom().nextLong());
//identify algorithm
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA512WithRSA");
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find( sigAlgId );

JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
JcaX509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(cert, serial, cert.getNotBefore(), cert.getNotAfter(),
            CSR.getSubject(), CSR.getPublicKey());
certGen.addExtension(Extension.authorityKeyIdentifier, false, extUtils.createAuthorityKeyIdentifier(cert));

certGen.addExtension(Extension.basicConstraints, true, new BasicConstraints(false));
certGen.addExtension(Extension.subjectKeyIdentifier, true, extUtils.createSubjectKeyIdentifier(inputCSR.getPublicKey()));
certGen.addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.dataEncipherment | KeyUsage.nonRepudiation));
ContentSigner signer = new JcaContentSignerBuilder(sigAlgName).setProvider("BC").build((PrivateKey)keystore.getKey(alias, password));
X509CertificateHolder holder = certGen.build(signer);
X509Certificate signedCert = new JcaX509CertificateConverter().setProvider("BC").getCertificate(holder);
signedCert.verify(cert.getPublicKey());
JcaPEMWriter pemWriter = new JcaPEMWriter(new FileWriter(new File("cer.cer")));
pemWriter.writeObject(signedCert);
pemWriter.writeObject(cert);
pemWriter.close();

现在正如我所说,生成的文件“cer.cer”中没有链。如何添加链?然后我可以将该签名证书发送回客户端并可以在 ssl 握手中使用吗?

【问题讨论】:

    标签: java ssl bouncycastle ca csr


    【解决方案1】:

    要添加链条,这对我有用

    X509CertificateHolder holder = certGen.build(signer);之后

      byte[] certencoded = holder.toASN1Structure().getEncoded();
      ContentSigner signer = new JcaContentSignerBuilder("SHA1withRSA").build(caPrivateKkey);
      CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
      generator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(signer, cacert));
      generator.addCertificate(new X509CertificateHolder(certencoded));
      generator.addCertificate(new X509CertificateHolder(cacert.getEncoded()));
      CMSTypedData content = new CMSProcessableByteArray(certencoded);
      CMSSignedData signeddata = generator.generate(content, true);
    
      byte certificateP7b[] = signedData.getEncoded();
    

    使用此代码,您将获得带有 PCKS#7 格式的完整链的证书。如果您更喜欢使用 X509 格式

    public static List<X509Certificate> p7BToX509(byte signedCert[]) throws CertificateException{
        ByteArrayInputStream is = new ByteArrayInputStream( signedCert);
        CertificateFactory cf = CertificateFactory.getInstance( "X.509" );
    
        ArrayList<X509Certificate> certificates = new ArrayList<X509Certificate>();
        Iterator i = cf.generateCertificates( is ).iterator();
        while ( i.hasNext() ){
           X509Certificate c = (X509Certificate)i.next();
           certificates.add(c);
    
        }
        return certificates;
    
    }
    

    这是公共证书。在您的客户端中,您应该拥有私钥。这些都是您需要执行和 ssl 握手的所有元素

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-30
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多