下面是java编程方式生成CA证书的代码,使用的是BC的provider。生成CA证书与生成普通证书的区别是:1,生成CA证书时,issuer和subject一致;2,在ContentSigner.build()的时候(签名的时候)使用的是与待签名公钥相应的私钥。

下面代码,CA生成以后把私钥和证书一起以一个key entry的方式存入一个jks文件。

  1.    static {  

  2.      Security.addProvider(new BouncyCastleProvider());  

  3. }  

  4. public static void main(String[] args) {  

  5.     try {  

  6.         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");  

  7.         kpg.initialize(2048);  

  8.         KeyPair keyPair = kpg.generateKeyPair();  

  9.         KeyStore store = KeyStore.getInstance("JKS");  

  10.         store.load(nullnull);  

  11.         String issuer = "C=CN,ST=GuangDong,L=Shenzhen,O=Skybility,OU=Cloudbility,CN=Atlas Personal License CA,E=cwjcsu@126.com";  

  12.         String subject = issuer;  

  13.         //issuer 与 subject相同的证书就是CA证书  

  14.         Certificate cert = generateV3(issuer, subject,  

  15.                 BigInteger.ZERO, new Date(System.currentTimeMillis() - 1000  

  16.                         * 60 * 60 * 24),  

  17.                 new Date(System.currentTimeMillis() + 1000L * 60 * 60 * 24  

  18.                         * 365 * 32), keyPair.getPublic(),//待签名的公钥  

  19.                 keyPair.getPrivate(), null);  

  20.         store.setKeyEntry("atlas", keyPair.getPrivate(),  

  21.                 "atlas".toCharArray(), new Certificate[] { cert });  

  22.         cert.verify(keyPair.getPublic());  

  23.         File file = new File("resource/atlas-ca.jks");  

  24.         if (file.exists() || file.createNewFile())  

  25.             store.store(new FileOutputStream(file), "atlas".toCharArray());  

  26.     } catch (Exception e) {  

  27.         e.printStackTrace();  

  28.     }  

  29. }  

  30. public static Certificate generateV3(String issuer, String subject,  

  31.         BigInteger serial, Date notBefore, Date notAfter,  

  32.         PublicKey publicKey, PrivateKey privKey, List<Extension> extensions)  

  33.         throws OperatorCreationException, CertificateException, IOException {  

  34.   

  35.     X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(  

  36.             new X500Name(issuer), serial, notBefore, notAfter,  

  37.             new X500Name(subject), publicKey);  

  38.     ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withRSA")  

  39.             .setProvider("BC").build(privKey);  

  40.     //privKey:使用自己的私钥进行签名,CA证书  

  41.     if (extensions != null)  

  42.         for (Extension ext : extensions) {  

  43.             builder.addExtension(new ASN1ObjectIdentifier(ext.getOid()),  

  44.                     ext.isCritical(),  

  45.                     ASN1Primitive.fromByteArray(ext.getValue()));  

  46.         }  

  47.     X509CertificateHolder holder = builder.build(sigGen);  

  48.     CertificateFactory cf = CertificateFactory.getInstance("X.509");  

  49.     InputStream is1 = new ByteArrayInputStream(holder.toASN1Structure()  

  50.             .getEncoded());  

  51.     X509Certificate theCert = (X509Certificate) cf.generateCertificate(is1);  

  52.     is1.close();  

  53.     return theCert;  

  54. }  

  55. public class Extension {  

  56.     private String oid;  

  57.     private boolean critical;  

  58.     private byte[] value;  

  59.   

  60.     public String getOid() {  

  61.         return oid;  

  62.     }  

  63.   

  64.     public byte[] getValue() {  

  65.         return value;  

  66.     }  

  67.   

  68.     public boolean isCritical() {  

  69.         return critical;  

  70.     }  

  71. }