【问题标题】:How to create PKCS#12 format file with client public certificate and private key using java program如何使用 java 程序创建带有客户端公共证书和私钥的 PKCS#12 格式文件
【发布时间】:2026-02-04 06:40:01
【问题描述】:

我有 .pem 格式文件形式的客户端公共证书和私钥文件。

你们中的任何人都可以帮助我如何使用 java 程序用这些文件创建 PKCS#12 格式文件。

这里我已经添加了我的代码

Path path = Paths.get(new File("User_privkey.pem").getAbsolutePath());
        Path certPath = Paths.get(new File("User.pem").getAbsolutePath());
        try {
            // Used to read User_privkey.pem file to get private key
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(Files.readAllBytes(path));
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(spec);

            //  Used to read user certificate 
            CertificateFactory factory = CertificateFactory.getInstance("X.509");
            Certificate cert = factory.generateCertificate(Files.newInputStream(certPath, null));

            KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
            // add it to the keystore
            ks.setKeyEntry("MyPKCSEntry", privateKey, "Temp".toCharArray(), new Certificate[] { cert });

            File file = new File("CERTIFICATE_CUSTOMPATH");
            OutputStream out = new FileOutputStream(file);
            ks.store(out, "Temp".toCharArray());
            out.close();

        } catch (Exception e) {
            System.out.println("Exception got caught" + e.getMessage());
        }

【问题讨论】:

标签: java ssl ssl-certificate pkcs#12


【解决方案1】:

你可以使用这个代码,我也推荐这个link

    public static byte[] pemToPKCS12(final String keyFile, final String cerFile, final String password) throws Exception {
// Get the private key
FileReader reader = new FileReader(keyFile);

PEMReader pem = new PEMReader(reader, new PasswordFinder() {
    @Override public char[] getPassword() {
        return password.toCharArray();
    }
});

PrivateKey key = ((KeyPair)pem.readObject()).getPrivate();

pem.close();
reader.close();

// Get the certificate      
reader = new FileReader(cerFile);
pem = new PEMReader(reader);

X509Certificate cert = (X509Certificate)pem.readObject();
java.security.cert.Certificate X509Certificate =
        new JcaX509CertificateConverter().setProvider("SC")
            .getCertificate(cert);
pem.close();
reader.close();

// Put them into a PKCS12 keystore and write it to a byte[]
ByteArrayOutputStream bos = new ByteArrayOutputStream();
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null);
ks.setKeyEntry("alias", (Key)key, password.toCharArray(), new java.security.cert.Certificate[]{cert});
ks.store(bos, password.toCharArray());
bos.close();
return bos.toByteArray();}

【讨论】:

  • 嗨,我遇到了以下异常。你能帮我解决这个问题吗 java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
  • 在上面的代码中,如果我没记错的话,你正在使用 bouncycastle api 来读取 pem 文件。请查看我现在使用的代码! PKCS8EncodedKeySpec 规范 = 新 PKCS8EncodedKeySpec(Files.readAllBytes(path)); PrivateKey privateKey = keyFactory.generatePrivate(spec);
  • KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PKCS8EncodedKeySpec 规范 = 新 PKCS8EncodedKeySpec(Files.readAllBytes(path)); PrivateKey privateKey = keyFactory.generatePrivate(spec); CertificateFactory 工厂 = CertificateFactory.getInstance("X.509");证书 cert = factory.generateCertificate(Files.newInputStream(certPath, null));
  • CertificateFactory 可以读取 PEM 文件,但 PKCS8EncodedKeySpec 不能。从 PEM 私钥中删除页眉和页脚并解码 base64
【解决方案2】:

需要对您的代码进行一些修复。请尝试这个功能齐全的代码。它不需要额外的依赖。我假设您的密钥是 PKCS#8(以 -----BEGIN PRIVATE KEY----- 开头。如果不是,您将不会转换它。

 public static void selfSignedCertificateToP12(String privateKeyFile, String certificateFile,String p12File, String alias, char[] password) 
        throws Exception{
    byte privateKeyData[] = Files.readAllBytes(Paths.get(privateKeyFile));
    byte certificateData[] = Files.readAllBytes(Paths.get(certificateFile));

    //Remove PEM header, footer and \n
    String privateKeyPEM = new String (privateKeyData, StandardCharsets.UTF_8);
    privateKeyPEM = privateKeyPEM.replace(
            "-----BEGIN PRIVATE KEY-----\n", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\n", "");
    byte privateKeyDER[] = Base64.getDecoder().decode(privateKeyPEM);

     // Used to read User_privkey.pem file to get private key
    PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privateKeyDER);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey privateKey = keyFactory.generatePrivate(spec);

    //  Used to read user certificate 
    CertificateFactory factory = CertificateFactory.getInstance("X.509");
    Certificate cert = factory.generateCertificate(new ByteArrayInputStream(certificateData));

    //Create keystore, add entry with the provided alias and save
    KeyStore ks = KeyStore.getInstance("PKCS12");
    ks.load(null);
    ks.setKeyEntry(alias, privateKey, password, new Certificate[] { cert });
    OutputStream out = new FileOutputStream(p12File);
    ks.store(out, password);
    out.close();
}

【讨论】: