将 PKCS10CertificationRequest 转换为 X509 证书

Convert PKCS10CertificationRequest to X509 certificate

我想知道是否可以使用 Bouncy Castle 将 PKCS10CertificationRequest 转换为 X509 证书?

类似于openssl中的X509_REQ_to_X509。

这是我创建请求的方式:

public static PKCS10CertificationRequest generateCSRFile(KeyPair keyPair, KeyUsage keyUsage) throws IOException, OperatorCreationException {
    String principal = "CA=" getCA();

    AsymmetricKeyParameter privateKey = PrivateKeyFactory.createKey(keyPair.getPrivate().getEncoded());
    AlgorithmIdentifier signatureAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder().find("SHA1WITHRSA");
    AlgorithmIdentifier digestAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find("SHA-1");
    ContentSigner signer = new BcRSAContentSignerBuilder(signatureAlgorithm, digestAlgorithm).build(privateKey);

    PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder(new X500Name(principal), keyPair.getPublic());
    ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator();
    extensionsGenerator.addExtension(X509Extension.basicConstraints, true, new BasicConstraints(true));
    extensionsGenerator.addExtension(X509Extension.keyUsage, true, keyUsage);
    csrBuilder.addAttribute(PKCSObjectIdentifiers.x509Certificate, extensionsGenerator.generate());
    PKCS10CertificationRequest csr = csrBuilder.build(signer);
    return csr;
}

我远不是 OpenSSL 专家,但根据我发现的一些文档:

X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey) creates an X509 certificate with subject and issuer the same as the subject in the request r, with validity days, and pkey used to sign it (with md5 as the digest).

这是 Bouncycastle 的等价物:

public X509Certificate x509ReqToX509(PKCS10CertificationRequest csr, int days, PrivateKey pKey) 
{
  Date notBefore = new Date();
  Calendar cal = Calendar.getInstance();
  cal.add(Calendar.DATE, days);
  Date notAfter = cal.getTime();
  BigInteger serialNumber = generateCertSerialNumber(); // No implemented here

  X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();

  certGen.setSerialNumber(serialNumber);
  certGen.setIssuerDN(csr.getCertificationRequestInfo().getSubject());
  certGen.setSubjectDN(csr.getCertificationRequestInfo().getSubject());
  certGen.setNotBefore(notBefore);
  certGen.setNotAfter(notAfter);
  certGen.setPublicKey(csr.getPublicKey());
  certGen.setSignatureAlgorithm("SHA256WithRSAEncryption");

  return certGen.generate(pKey, "BC");
}

注意:

  1. 我在签名算法中用SHA-256替换了MD5
  2. 根据证书的目的,这个简短的代码示例可能需要一些更新(例如,添加一些强制扩展)