如何用Java生成证书?Spring Boot私钥存入密钥库的证书获取方法
使用Sun Provider生成自签名证书并将私钥存入密钥库
要把私钥存入Sun Provider默认的JKS密钥库,必须搭配对应证书——完全可以用Sun Provider原生工具生成自签名证书,不需要依赖BouncyCastle。以下是完整实现流程:
1. 复用密钥对生成逻辑
你的密钥对生成代码可以直接保留,这里修正了全局变量问题:
public static KeyPair createKeyPair(final String algorithm, final String cryptoProvider, final int keySize) throws NoSuchAlgorithmException, NoSuchProviderException { checkCryptoProvider(cryptoProvider); KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm, cryptoProvider); keyPairGenerator.initialize(keySize); return keyPairGenerator.generateKeyPair(); } private static void checkCryptoProvider(String cryptoProvider) { if (Security.getProvider(cryptoProvider) == null) { throw new IllegalArgumentException("Crypto provider not found: " + cryptoProvider); } }
2. 纯Sun Provider生成自签名证书
通过Sun Provider内部的sun.security.x509工具类构造自签名证书,全程依赖Sun原生实现:
import java.math.BigInteger; import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.X509Certificate; import java.util.Date; import sun.security.x509.CertificateAlgorithmId; import sun.security.x509.CertificateSerialNumber; import sun.security.x509.CertificateVersion; import sun.security.x509.CertificateX509Key; import sun.security.x509.X500Name; import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertInfo; import sun.security.x509.Validity; public static X509Certificate generateSelfSignedCert(KeyPair keyPair, String issuerDn, long validityDays) throws Exception { PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); // 设置证书有效期(当前时间起N天内有效) Date startDate = new Date(); Date endDate = new Date(startDate.getTime() + validityDays * 24 * 60 * 60 * 1000); // 生成唯一证书序列号 BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis()); // 构造证书核心信息 X509CertInfo certInfo = new X509CertInfo(); X500Name subjectIssuer = new X500Name(issuerDn); // 自签名证书的颁发者和主体一致 certInfo.set(X509CertInfo.VALIDITY, new Validity(startDate, endDate)); certInfo.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serialNumber)); certInfo.set(X509CertInfo.SUBJECT, subjectIssuer); certInfo.set(X509CertInfo.ISSUER, subjectIssuer); certInfo.set(X509CertInfo.KEY, new CertificateX509Key(publicKey)); certInfo.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); certInfo.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId( sun.security.x509.AlgorithmId.get("SHA256withRSA"))); // 用私钥签名证书,完成合法性绑定 X509CertImpl cert = new X509CertImpl(certInfo); cert.sign(privateKey, "SHA256withRSA"); return cert; }
3. 将私钥与证书存入JKS密钥库
使用Sun Provider默认的JKS密钥库类型,完成私钥和证书的持久化:
import java.io.FileOutputStream; import java.security.KeyStore; import java.security.cert.X509Certificate; public static void saveToKeyStore(KeyPair keyPair, X509Certificate cert, String storePath, String storePass, String keyAlias) throws Exception { // 初始化新的JKS密钥库 KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(null, storePass.toCharArray()); // 将私钥与证书链存入密钥库(自签名证书只有1个证书) keyStore.setKeyEntry(keyAlias, keyPair.getPrivate(), storePass.toCharArray(), new X509Certificate[]{cert}); // 写入文件 try (FileOutputStream fos = new FileOutputStream(storePath)) { keyStore.store(fos, storePass.toCharArray()); } }
使用示例
public static void main(String[] args) throws Exception { // 生成RSA密钥对,指定SunRsaSign Provider KeyPair keyPair = createKeyPair("RSA", "SunRsaSign", 2048); // 生成自签名证书,DN格式遵循X.500规范 X509Certificate cert = generateSelfSignedCert(keyPair, "CN=KeyGenAPI, OU=Dev, O=MyOrg, L=Shanghai, ST=Shanghai, C=CN", 365); // 存入本地JKS密钥库 saveToKeyStore(keyPair, cert, "./my-keystore.jks", "mySecurePass123", "api-key-pair"); }
注意事项
sun.security.x509属于JDK内部API,在Oracle JDK和OpenJDK中均兼容,但如果未来JDK版本调整内部API,可能需要适配。如果追求完全基于公开API的实现,可选用BouncyCastle的证书构建工具,但底层签名仍可指定Sun Provider。- 实际场景建议将密钥库密码与私钥密码分开设置,提升安全性。
- 自签名证书仅适合内部系统或测试环境使用,对外服务建议使用CA颁发的正规证书。
内容的提问来源于stack exchange,提问作者Sinnedkid
相关产品推荐
相关产品推荐

