目录
一、说明
二、实现代码
三、结果分析
一、说明
最近在做一个项目,涉及到数字证书这一块的内容,其中有一个需求是,根据前端维护上送参数, 后台Java实现生成cer自签名证书,证书要求跟openssl命令生成的一样 ,我的java环境是JDK1.8。
网络--keytool CA签名SSL证书(收费)
网络--keytool自签名SSL证书(免费)以及私钥签名、公钥验签
二、实现代码
package com.justin.key;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.HashMap;
import org.bouncycastle.asn1.x509.X509Name;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.x509.X509V3CertificateGenerator;
import sun.misc.BASE64Encoder;
public class CreateCerFile {
private String path = "E:/";
private static String CTFC_DOMAIN_NAME = "domainName";
private static String CTFC_ORG_UNIT_NAME = "orgUnitName";
private static String CTFC_ORG_NAME = "orgName";
private static String CTFC_COUNTRY_CODE = "countryCode";
private static String CTFC_CITY = "city";
private static String CTFC_PROVINCE = "province";
private static String CTFC_VALID_START_TIME = "validStartTime";
private static String CTFC_VALID_END_TIME = "validEndTime";
private static String CTFC_SERIAL_NUMBER = "serialNumber";
private static String CTFC_SIG_AlG = "signatureAlgorithm";
private static String CTFC_ENCRYPT_TYPE = "encryptType";
private static String CTFC_ENCRYPT_NUM = "encryptNum";
private static String CTFC_PROVIDER = "provider";
static {
Security.addProvider(new BouncyCastleProvider());
}
public X509Certificate generateCert(HashMap<String,Object> infoMap, KeyPair keyPair_root, KeyPair keyPair_user)
throws InvalidKeyException, NoSuchProviderException, SecurityException, SignatureException {
X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
X509Certificate cert = null;
certGen.setSerialNumber((BigInteger)infoMap.get(CTFC_SERIAL_NUMBER));
certGen.setIssuerDN(new X509Name("CN="+ (String)infoMap.get(CTFC_DOMAIN_NAME)));
certGen.setNotBefore((Date)infoMap.get(CTFC_VALID_START_TIME));
certGen.setNotAfter((Date)infoMap.get(CTFC_VALID_END_TIME));
certGen.setSubjectDN(new X509Name("CN=" + (String)infoMap.get(CTFC_DOMAIN_NAME)));
certGen.setPublicKey(keyPair_user.getPublic());
certGen.setSignatureAlgorithm((String)infoMap.get(CTFC_SIG_AlG));
cert = certGen.generateX509Certificate(keyPair_root.getPrivate(), (String)infoMap.get(CTFC_PROVIDER));
return cert;
}
public KeyPair generateKeyPair(HashMap<String,Object> infoMap,int seed) throws NoSuchAlgorithmException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance((String)infoMap.get(CTFC_ENCRYPT_TYPE));
kpg.initialize((int)infoMap.get(CTFC_ENCRYPT_NUM),new SecureRandom(new byte[seed]));
KeyPair keyPair = kpg.generateKeyPair();
return keyPair;
}
public boolean createCerFile(HashMap<String,Object> infoMap) {
try {
KeyPair keyPair_root = generateKeyPair(infoMap,10);
KeyPair keyPair_user = generateKeyPair(infoMap,10);
X509Certificate cert = generateCert(infoMap, keyPair_root, keyPair_user);
String certPath = path + infoMap.get(CTFC_DOMAIN_NAME) + ".cer";
FileOutputStream fos = new FileOutputStream(certPath);
fos.write(cert.getEncoded());
fos.close();
return true;
} catch (Exception e) {
e.printStackTrace();
System.out.println("createPublicKey error:" + e.getMessage());
return false;
}
}
public boolean createBase64CerFileByDecode(HashMap<String,Object> infoMap) {
try {
KeyPair keyPair_root = generateKeyPair(infoMap,10);
KeyPair keyPair_user = generateKeyPair(infoMap,10);
X509Certificate cert = generateCert(infoMap, keyPair_root, keyPair_user);
String certPath = path + infoMap.get(CTFC_DOMAIN_NAME) + "_base64.cer";
String encode = new BASE64Encoder().encode(cert.getEncoded());
String base64EncodeCer = "-----BEGIN CERTIFICATE-----\r\n" + encode + "\r\n-----END CERTIFICATE-----\r\n";
FileWriter wr = new java.io.FileWriter(new File(certPath));
wr.write(base64EncodeCer);
wr.flush();
wr.close();
return true;
} catch (Exception e) {
e.printStackTrace();
System.out.println("createPublicKeyByDecode error:" + e.getMessage());
return false;
}
}
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, SecurityException, SignatureException, CertificateEncodingException, IOException {
CreateCerFile dataCertCreate = new CreateCerFile();
Date validStartTime = new Date();
Date validEndTime = new Date(validStartTime.getTime() + 10*365L*24L*60L*60L*1000L);
BigInteger serialNumber = new BigInteger(String.valueOf(validStartTime.getTime() / 1000L));
HashMap<String,Object> infoMap = new HashMap<String,Object>();
infoMap.put(CTFC_DOMAIN_NAME, "www.justinqin.com");
infoMap.put(CTFC_ORG_UNIT_NAME, "orgUnitName");
infoMap.put(CTFC_ORG_NAME, "orgName");
infoMap.put(CTFC_COUNTRY_CODE, "CN");
infoMap.put(CTFC_CITY, "深圳市");
infoMap.put(CTFC_PROVINCE, "广东省");
infoMap.put(CTFC_VALID_START_TIME, validStartTime);
infoMap.put(CTFC_VALID_END_TIME, validEndTime);
infoMap.put(CTFC_SERIAL_NUMBER, serialNumber);
infoMap.put(CTFC_SIG_AlG, "SHA256withRSA");
infoMap.put(CTFC_ENCRYPT_TYPE, "RSA");
infoMap.put(CTFC_ENCRYPT_NUM, 2048);
infoMap.put(CTFC_PROVIDER, "BC");
boolean createCerFileRs = dataCertCreate.createCerFile(infoMap);
System.out.println("createCerFile, result==" + createCerFileRs);
boolean createBase64CerFileByDecodeRs = dataCertCreate.createBase64CerFileByDecode(infoMap);
System.out.println("createBase64CerFileByDecode, result==" + createBase64CerFileByDecodeRs);
}
}
三、结果分析
实现代码运行结果:
createCerFile, result==true
createBase64CerFileByDecode, result==true
生成cer证书文件信息如下:

PS:
生成cer证书的generateCert()方法需要确保,certGen赋值足够的参数,否则可能会生成证书失败,抛异常信息,例如我们把generateCert()方法中设置证书有效起始时间 、证书有效截止时间的代码注释掉,再运行
则报错提示如下:
java.lang.IllegalStateException: not all mandatory fields set in V3 TBScertificate generatorcreatePublicKey error:not all mandatory fields set in V3 TBScertificate generator
createCerFile, result==false
at org.bouncycastle.asn1.x509.V3TBSCertificateGenerator.generateTBSCertificate(Unknown Source)
at org.bouncycastle.x509.X509V3CertificateGenerator.generateTbsCert(Unknown Source)
at org.bouncycastle.x509.X509V3CertificateGenerator.generate(Unknown Source)
at org.bouncycastle.x509.X509V3CertificateGenerator.generateX509Certificate(Unknown Source)
at org.bouncycastle.x509.X509V3CertificateGenerator.generateX509Certificate(Unknown Source)
at com.justin.key.CreateCerFile.generateCert(CreateCerFile.java:97)
at com.justin.key.CreateCerFile.createCerFile(CreateCerFile.java:125)
at com.justin.key.CreateCerFile.main(CreateCerFile.java:198)
createPublicKeyByDecode error:not all mandatory fields set in V3 TBScertificate generator
createBase64CerFileByDecode, result==false
java.lang.IllegalStateException: not all mandatory fields set in V3 TBScertificate generator
at org.bouncycastle.asn1.x509.V3TBSCertificateGenerator.generateTBSCertificate(Unknown Source)
at org.bouncycastle.x509.X509V3CertificateGenerator.generateTbsCert(Unknown Source)
at org.bouncycastle.x509.X509V3CertificateGenerator.generate(Unknown Source)
at org.bouncycastle.x509.X509V3CertificateGenerator.generateX509Certificate(Unknown Source)
at org.bouncycastle.x509.X509V3CertificateGenerator.generateX509Certificate(Unknown Source)
at com.justin.key.CreateCerFile.generateCert(CreateCerFile.java:97)
at com.justin.key.CreateCerFile.createBase64CerFileByDecode(CreateCerFile.java:152)
at com.justin.key.CreateCerFile.main(CreateCerFile.java:201)
评论(0)