Spring Boot项目引入BouncyCastle后X509v3CertificateBuilder无法解析
问题解决:X509v3CertificateBuilder无法解析及其他自签名证书生成方法
一、X509v3CertificateBuilder无法解析的原因及修复
你添加的bcprov-jdk15on依赖仅包含BouncyCastle的核心加密算法实现,org.bouncycastle.cert包(包括X509v3CertificateBuilder类)并不在这个依赖中,它属于BouncyCastle的PKIX/CMS扩展库bcpkix-jdk15on。
修复步骤:
- 在
build.gradle.kts中补充添加bcpkix-jdk15on依赖:
dependencies { // 原核心加密依赖 implementation("org.bouncycastle:bcprov-jdk15on:1.70") // 新增PKIX扩展依赖,包含X509v3CertificateBuilder implementation("org.bouncycastle:bcpkix-jdk15on:1.70") }
- 执行Gradle同步操作(IntelliJ中点击右上角的"Sync Project with Gradle Files"按钮)。
- 如果同步后仍无法识别,尝试清理IDE缓存:
File -> Invalidate Caches... -> 勾选"Clear file system cache and local history" -> 点击Invalidate and Restart。
二、其他生成自签名X.509证书的方法
1. 使用JDK自带的keytool命令行
这是最简便的方式,无需编写代码:
# 生成自签名证书,有效期3650天,存储在keystore文件中 keytool -genkeypair -alias myselfsigned -keyalg RSA -keysize 2048 -validity 3650 -keystore mykeystore.jks -storepass mypassword
参数说明:
-alias:证书别名-keyalg:加密算法(推荐RSA)-keysize:密钥长度(至少2048)-validity:有效期(天数)-keystore:密钥库文件路径-storepass:密钥库密码
2. 使用Java原生API(无需第三方库)
通过JDK自带的java.security包实现,示例代码:
import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.cert.X509Certificate; import java.util.Date; import javax.security.auth.x500.X500Principal; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertInfo; public class SelfSignedCertGenerator { public static X509Certificate generateSelfSignedCert(String subjectDN) throws Exception { // 生成RSA密钥对 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048); KeyPair keyPair = keyPairGen.generateKeyPair(); // 构造证书信息 X509CertInfo certInfo = new X509CertInfo(); Date startDate = new Date(); Date endDate = new Date(startDate.getTime() + 3650 * 24 * 60 * 60 * 1000L); // 10年有效期 certInfo.set(X509CertInfo.VALIDITY, new sun.security.x509.Validity(startDate, endDate)); certInfo.set(X509CertInfo.SUBJECT, new X500Principal(subjectDN)); certInfo.set(X509CertInfo.ISSUER, new X500Principal(subjectDN)); // 自签名,签发者与主体一致 certInfo.set(X509CertInfo.KEY, new sun.security.x509.X509Key(keyPair.getPublic())); certInfo.set(X509CertInfo.SERIAL_NUMBER, new sun.security.x509.SerialNumber(new java.util.Random().nextLong())); certInfo.set(X509CertInfo.VERSION, new sun.security.x509.CertificateVersion(CertificateVersion.V3)); certInfo.set(X509CertInfo.ALGORITHM_ID, new sun.security.x509.AlgorithmId(sun.security.x509.AlgorithmId.md5WithRSAEncryption_oid)); // 生成并签名证书 X509CertImpl cert = new X509CertImpl(certInfo); cert.sign(keyPair.getPrivate(), "SHA256withRSA"); return cert; } }
注意:sun.security包属于JDK内部API,部分环境可能会限制访问,若出现编译警告或错误,可在Gradle中添加参数允许使用内部API:
tasks.withType<JavaCompile> { options.compilerArgs.add("--add-exports=java.base/sun.security.x509=ALL-UNNAMED") }
3. 使用BouncyCastle的完整实现(修复依赖后)
添加bcpkix-jdk15on依赖后,可使用X509v3CertificateBuilder生成证书,示例代码:
import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.cert.X509Certificate; import java.util.Date; public class BouncyCastleCertGenerator { public static X509Certificate generateSelfSignedCert(String subjectDN) throws Exception { // 生成RSA密钥对 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); keyPairGen.initialize(2048); KeyPair keyPair = keyPairGen.generateKeyPair(); X500Name issuer = new X500Name(subjectDN); X500Name subject = new X500Name(subjectDN); Date startDate = new Date(); Date endDate = new Date(startDate.getTime() + 3650 * 24 * 60 * 60 * 1000L); // 构造证书构建器 X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( issuer, java.math.BigInteger.valueOf(System.currentTimeMillis()), startDate, endDate, subject, keyPair.getPublic() ); // 签名证书 X509Certificate cert = new JcaX509CertificateConverter() .getCertificate(certBuilder.build(new JcaContentSignerBuilder("SHA256withRSA").build(keyPair.getPrivate()))); return cert; } }
内容的提问来源于stack exchange,提问作者user842225
相关产品推荐
相关产品推荐

