<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.64</version> </dependency>
CSR,即证书请求文件(Certificate Signing Request)。生成 X509 数字证书前,通常先由用户提交证书申请文件,而后由 CA 来签发证书。java
// 建立密钥对 KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); gen.initialize(2048); KeyPair pair = gen.generateKeyPair(); PrivateKey privateKey = pair.getPrivate(); PublicKey publicKey = pair.getPublic(); // 建立 CSR 对象 X500Principal subject = new X500Principal("C=CName, ST=STName, L=LName, O=OName, OU=OUName, CN=CNName, EMAILADDRESS=Name@gmail.com"); ContentSigner signGen = new JcaContentSignerBuilder("SHA256withRSA").build(privateKey); PKCS10CertificationRequestBuilder builder = new JcaPKCS10CertificationRequestBuilder(subject, publicKey); // 添加 SAN 扩展 ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator(); GeneralNames generalNames = new GeneralNames(new GeneralName[]{new GeneralName(GeneralName.rfc822Name, "ip=6.6.6.6"), new GeneralName(GeneralName.rfc822Name, "email=666@gmail.com")}); extensionsGenerator.addExtension(Extension.subjectAlternativeName, false, generalNames); builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, extensionsGenerator.generate()); // build csr PKCS10CertificationRequest csr = builder.build(signGen); // 输出 PEM 格式的 CSR OutputStreamWriter output = new OutputStreamWriter(System.out); JcaPEMWriter pem = new JcaPEMWriter(output); pem.writeObject(csr); pem.close();
PEM 格式 CSR 示例以下:(PER 是对 DER 的简单包装)web
-----BEGIN CERTIFICATE REQUEST----- MIIC5DCCAcwCAQAwgZ4xIjAgBgkqhkiG9w0BCQEWE3NlbnRoYWRldkBnbWFpbC5j b20xGjAYBgNVBAMTEXd3dy5zZW50aGFkZXYuY29tMRMwEQYDVQQLEwpJbm5vdmF0 aW9uMRIwEAYDVQQKEwlTZW50aGFkZXYxEjAQBgNVBAcTCVRyb25kaGVpbTESMBAG A1UECBMJVHJvbmRoZWltMQswCQYDVQQGEwJOTzCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAMkKvsCUp52lcmM//iJEV62yHzDS/ASwm0wmlbUR+OnxESA5 vsYYzqdxX/Ie+K4LqY/FKsnHwcj+l7PqIHPqgiDryMcfYFpmln31jJG6XPFmjBib m0kl63G9T62EyoRYo7SFZq/wcdgEE0FTw4bnTyT5OED2cYRlozBXdnI0L9jZYv6b R6ww4LD4cAkqq1TeKNt0lH5G7S8QqTIeobs7hYUgVXkKWhfrYrW0l4lYUuXC12sN e/zGYClHoaFoasD9pzoFrVjDS9+a3JoInp22OxpQbBVchnOJ3yJr8PRS5Hzx5QYJ TAYqUd8dsw372FhvnNlZJnSkAsxca7cfpCiL4ZECAwEAAaAAMA0GCSqGSIb3DQEB BQUAA4IBAQDDTj7ZJaeRftrod5TuEPoDhH8SwCx/wX8aIYG3mjR+q8tJ6rYgPwqR Du8ODOAgIRFC8Dk43taPhbL94+T+iyw+UJH1KGlf0cdfHvaPoTh6QqfIQHRXuq5H hkb9g+DgG/uzIS0yQsviKCTwFOZkvaWMZQSlBkAzFf61NQ9ymjLRFnzUN3IBmxMU VBBEVVchta79XtkQaOsHWaZPpuwvDEtrvvwjk6kIEsc7IU927nN1Vws9oDFsqrKl ycNVfwjd0cgf5WsTbPnBjQdVSSdAWvJo1wLrv3GxGVUwi44TzVU0xvREYAmZknCW kpMkr5KBOO3Prex5d0doD5MJhMvxHcSL -----END CERTIFICATE REQUEST-----
首先,读取、解析 CSR 文件:ide
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider()); // 解析 PEM 格式的 CSR PKCS10CertificationRequest csr = null; ByteArrayInputStream pemStream = new ByteArrayInputStream(pem.getBytes(Charsets.UTF_8)); Reader pemReader = new BufferedReader(new InputStreamReader(pemStream)); PEMParser pemParser = new PEMParser(pemReader); Object parsedObj = pemParser.readObject(); System.out.println("PemParser returned: " + parsedObj); if (parsedObj instanceof PKCS10CertificationRequest) { csr = (PKCS10CertificationRequest) parsedObj; }
利用 PKCS10CertificationRequest 枪法证书svg
KeyPair rootPair = KeyUtil.generateKeyPair("RSA", 4096); // 私钥用来前面 PrivateKey issuePriveteKey = rootPair.getPrivate(); X509Certificate rootCert = // 利用公钥建立根证书,来签发用户证书 X509v3CertificateBuilder certificateBuilder = new X509v3CertificateBuilder( new X500Name(rootCert.getSubjectDN().getName()), BigInteger.valueOf(666666666L), new Date(), new Date(System.currentTimeMillis() + 1000 * 86400 * 365L), pkcs10CertificationRequest.getSubject(), pkcs10CertificationRequest.getSubjectPublicKeyInfo() ); // 读取扩展信息 Extensions extensions = null; for (Attribute attr : pkcs10CertificationRequest.getAttributes()) { if (PKCSObjectIdentifiers.pkcs_9_at_extensionRequest.equals(attr.getAttrType())) { extensions = Extensions.getInstance(attr.getAttributeValues()[0]); break; } } if (extensions != null) { // 添加 SAN 扩展 certificateBuilder.addExtension(extensions.getExtension(Extension.subjectAlternativeName)); } //添加crl扩展 GeneralName[] names = new GeneralName[1]; names[0] = new GeneralName(GeneralName.uniformResourceIdentifier, "http://www.ca.com/crl"); GeneralNames gns = new GeneralNames(names); DistributionPointName pointName = new DistributionPointName(gns); GeneralNames crlIssuer = new GeneralNames(new GeneralName(new X500Name(rootCert.getSubjectDN().getName()))); DistributionPoint[] points = new DistributionPoint[1]; points[0] = new DistributionPoint(pointName, null, crlIssuer); certificateBuilder.addExtension(Extension.cRLDistributionPoints, false, new CRLDistPoint(points)); //添加aia扩展 AccessDescription[] accessDescriptions = new AccessDescription[2]; accessDescriptions[0] = new AccessDescription(AccessDescription.id_ad_caIssuers, new GeneralName(GeneralName.uniformResourceIdentifier, "http://www.ca.com/root.crt")); accessDescriptions[1] = new AccessDescription(AccessDescription.id_ad_ocsp, new GeneralName(GeneralName.uniformResourceIdentifier, "http://ocsp.com/")); certificateBuilder.addExtension(Extension.authorityInfoAccess, false, new AuthorityInformationAccess(accessDescriptions)); ContentSigner signer = new JcaContentSignerBuilder(HostCertificateConf.CERTIFICATE_SIGNATURE_ALGORITHM) .setProvider(Security.getProvider("BC")).build(issuePriveteKey); X509CertificateHolder holder = certificateBuilder.build(signer); X509Certificate cert = new JcaX509CertificateConverter() .setProvider(Security.getProvider( "BC")).getCertificate(holder);