You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何生成合法X.509证书以获取公钥?Java模块错误解决

如何生成有效X.509证书以获取公钥?

现有从证书字符串提取公钥的代码

private PublicKey getKey(String certificateValue) {
    try {
      CertificateFactory cf = CertificateFactory.getInstance("X.509");
      ByteArrayInputStream bis =
          new ByteArrayInputStream(certificateValue.getBytes(StandardCharsets.UTF_8));

      Certificate certificate = null;
      while (bis.available() > 0) {
        certificate = cf.generateCertificate(bis);
      }

      return certificate.getPublicKey();
  }

遇到的编译错误

尝试使用sun.security.x509包生成X.509证书时,触发以下编译错误:

import sun.security.x509.*;
                   ^
  (package sun.security.x509 is declared in module java.base, which does not export it to the unnamed module)

原因是sun.security.x509属于Java内部私有API,Java 9及以后的模块化系统禁止未命名模块直接访问这类内部包,且该API不具备跨版本兼容性,绝对不建议使用。

正确生成X.509证书的方案

方案1:使用BouncyCastle(兼容Java 8+)

BouncyCastle是广泛使用的开源安全库,提供了稳定的X.509证书生成能力:

  1. 添加Maven依赖:
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.70</version>
</dependency>
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15on</artifactId>
    <version>1.70</version>
</dependency>
  1. 生成自签名X.509证书代码:
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Date;

public X509Certificate generateSelfSignedCertificate() throws Exception {
    // 生成2048位RSA密钥对
    KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
    keyPairGenerator.initialize(2048, new SecureRandom());
    KeyPair keyPair = keyPairGenerator.generateKeyPair();

    // 设置证书有效期为1年
    long validityMillis = 365 * 24 * 60 * 60 * 1000L;
    Date startDate = new Date();
    Date endDate = new Date(startDate.getTime() + validityMillis);

    // 定义证书颁发者/使用者信息
    X500Name subject = new X500Name("CN=SelfSignedCert, OU=Dev, O=Example, L=Beijing, ST=Beijing, C=CN");

    // 构建证书
    JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
            subject,
            BigInteger.valueOf(System.currentTimeMillis()),
            startDate,
            endDate,
            subject,
            keyPair.getPublic()
    );

    // 用私钥签名证书
    JcaContentSignerBuilder signerBuilder = new JcaContentSignerBuilder("SHA256withRSA");
    return new JcaX509CertificateConverter().getCertificate(certBuilder.build(signerBuilder.build(keyPair.getPrivate())));
}

方案2:使用Java 11+标准API(无需第三方库)

Java 11及以上内置了标准证书生成API,无需额外依赖:

import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import java.security.cert.CertificateBuilder;
import java.security.cert.X509Certificate;
import java.util.Date;

public X509Certificate generateSelfSignedCert() throws Exception {
    // 生成RSA密钥对
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    kpg.initialize(2048);
    KeyPair kp = kpg.generateKeyPair();

    // 设置证书有效期
    Date start = new Date();
    Date end = new Date(start.getTime() + 365L * 24 * 60 * 60 * 1000);

    // 构建并生成自签名证书
    CertificateBuilder builder = CertificateBuilder.getInstance("X.509");
    builder.setIssuer("CN=SelfSigned, O=Example")
           .setSubject("CN=SelfSigned, O=Example")
           .setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()))
           .setNotBefore(start)
           .setNotAfter(end)
           .setPublicKey(kp.getPublic())
           .sign(kp.getPrivate(), "SHA256withRSA");

    return (X509Certificate) builder.build();
}

将证书转换为字符串供getKey方法使用

生成证书后,将其转换为PEM格式字符串,即可直接传入你的getKey方法:

import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateEncodingException;
import java.util.Base64;

public String certToPemString(X509Certificate cert) throws CertificateEncodingException {
    byte[] certBytes = cert.getEncoded();
    String base64Cert = Base64.getEncoder().encodeToString(certBytes);
    return "-----BEGIN CERTIFICATE-----\n" + base64Cert + "\n-----END CERTIFICATE-----";
}

内容的提问来源于stack exchange,提问作者Peter Penzov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 05:15:42