/**
* 签发证书
*
* @param p10Obj 证书请求ASN1对象
* @param root CA根证书
* @param privateKey CA私钥
* @return X509证书对象
*/
public static X509Certificate GenCert(PKCS10CertificationRequest p10Obj,
Certificate root,
PrivateKey privateKey)
throws GeneralSecurityException,
IOException,
OperatorCreationException {
JcaPKCS10CertificationRequest req = new JcaPKCS10CertificationRequest(p10Obj);
// 从证书请求中获取到使用DN
X500Name subject = req.getSubject();
// 取得根证书的Subject,签发证书的使用者就是根证书的使用者
X500Name issuer = new X509CertificateHolder(root.getEncoded())
.getSubject();
// 根据需求构造实体证书
X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(
// 颁发者信息
issuer
// 证书序列号
, BigInteger.valueOf(Instant.now().toEpochMilli())
// 证书生效日期
, Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant())
// 证书失效日期
, Date.from(LocalDateTime.now().plusYears(2).atZone(ZoneId.systemDefault()).toInstant())
// 使用者信息
, subject
// 证书公钥
, req.getPublicKey())
// 设置密钥用法
.addExtension(Extension.keyUsage,
false
, new X509KeyUsage(X509KeyUsage.digitalSignature
| X509KeyUsage.nonRepudiation
| X509KeyUsage.keyCertSign))
// 设置扩展密钥用法:客户端身份认证
.addExtension(Extension.extendedKeyUsage,
false,
new ExtendedKeyUsage(KeyPurposeId.id_kp_clientAuth))
// 基础约束,标识是否是CA证书,这里false标识为实体证书
.addExtension(Extension.basicConstraints,
false,
new BasicConstraints(false))
// Netscape Cert Type SSL客户端身份认证
.addExtension(MiscObjectIdentifiers.netscapeCertType,
false,
new NetscapeCertType(NetscapeCertType.sslClient));
// 5. 证书签名实现类
ContentSigner sigGen = new JcaContentSignerBuilder("SM3withSM2")
.setProvider("BC")
.build(privateKey);
// 6. 签发证书
return new JcaX509CertificateConverter()
.setProvider("BC")
.getCertificate(certGen.build(sigGen));
}