下面是java编程方式生成CA证书的代码,使用的是BC的provider。生成CA证书与生成普通证书的区别是:1,生成CA证书时,issuer和subject一致;2,在ContentSigner.build()的时候(签名的时候)使用的是与待签名公钥相应的私钥。
下面代码,CA生成以后把私钥和证书一起以一个key entry的方式存入一个jks文件。
static {
Security.addProvider(new BouncyCastleProvider());
}
public static void main(String[] args) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair keyPair = kpg.generateKeyPair();
KeyStore store = KeyStore.getInstance("JKS");
store.load(null, null);
String issuer = "C=CN,ST=GuangDong,L=Shenzhen,O=Skybility,OU=Cloudbility,CN=Atlas Personal License CA,E=cwjcsu@126.com";
String subject = issuer;
//issuer 与 subject相同的证书就是CA证书
Certificate cert = generateV3(issuer, subject,
BigInteger.ZERO, new Date(System.currentTimeMillis() - 1000
* 60 * 60 * 24),
new Date(System.currentTimeMillis() + 1000L * 60 * 60 * 24
* 365 * 32), keyPair.getPublic(),//待签名的公钥
keyPair.getPrivate(), null);
store.setKeyEntry("atlas", keyPair.getPrivate(),
"atlas".toCharArray(), new Certificate[] { cert });
cert.verify(keyPair.getPublic());
File file = new File("resource/atlas-ca.jks");
if (file.exists() || file.createNewFile())
store.store(new FileOutputStream(file), "atlas".toCharArray());
} catch (Exception e) {
e.printStackTrace();
}
}
public static Certificate generateV3(String issuer, String subject,
BigInteger serial, Date notBefore, Date notAfter,
PublicKey publicKey, PrivateKey privKey, List<Extension> extensions)
throws OperatorCreationException, CertificateException, IOException {
X509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
new X500Name(issuer), serial, notBefore, notAfter,
new X500Name(subject), publicKey);
ContentSigner sigGen = new JcaContentSignerBuilder("SHA1withRSA")
.setProvider("BC").build(privKey);
//privKey:使用自己的私钥进行签名,CA证书
if (extensions != null)
for (Extension ext : extensions) {
builder.addExtension(new ASN1ObjectIdentifier(ext.getOid()),
ext.isCritical(),
ASN1Primitive.fromByteArray(ext.getValue()));
}
X509CertificateHolder holder = builder.build(sigGen);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream is1 = new ByteArrayInputStream(holder.toASN1Structure()
.getEncoded());
X509Certificate theCert = (X509Certificate) cf.generateCertificate(is1);
is1.close();
return theCert;
}
public class Extension {
private String oid;
private boolean critical;
private byte[] value;
public String getOid() {
return oid;
}
public byte[] getValue() {
return value;
}
public boolean isCritical() {
return critical;
}
}