Java证书操作

  1. 如何将公钥、私钥字符串转换为pfx证书
java 复制代码
/**
 * 前置要求:
 *  1. jdk1.8
 *  2. 引入依赖:
 *    <dependency>
 *          <groupId>org.bouncycastle</groupId>
 *           <artifactId>bcprov-jdk15on</artifactId>
 *            <version>1.70</version>
 *    </dependency>
 * 相关资源 :https://www.ssleye.com/ssltool/jks_pkcs12.html
 *@author starSky
 *@datetime 2026/1/28 18:31
 */

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Enumeration;

public class JksGenerator {
    /**
     * 将 JKS 转换为 PKCS#12(PFX)格式
     * 适用于 Java 8
     */
    static {
        // 注册 Bouncy Castle 提供者
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * 从 PEM 证书文件加载证书(推荐方式)
     */
    public static Certificate loadCertificateFromPem(String certPem) throws Exception {
        String certStr = certPem.replace("-----BEGIN CERTIFICATE-----", "").replace("-----END CERTIFICATE-----", "").replace("\n", "").replace("\r", "").trim();

        byte[] certBytes = Base64.getDecoder().decode(certStr);
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        return certFactory.generateCertificate(new ByteArrayInputStream(certBytes));
    }

    /**
     * 使用现有证书生成 JKS(推荐方案)
     * @param privateKeyPem 私钥
     * @param certPem 公钥
     * @param alias 别名
     * @param jksPath 输出路径
     * @param keystorePassword keystore 密码
     * @param keyPassword key 密码
     */
    public static void generateJksWithCert(String privateKeyPem, String certPem, String alias, String jksPath, String keystorePassword, String keyPassword) throws Exception {

        // 解析私钥
        String privateKeyStr = privateKeyPem.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replace("\n", "").replace("\r", "").trim();

        byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

        // 加载证书
        Certificate cert = loadCertificateFromPem(certPem);

        // 创建 KeyStore
        KeyStore keyStore = KeyStore.getInstance("JKS");
        char[] ksPassword = keystorePassword.toCharArray();
        keyStore.load(null, ksPassword);

        // 设置密钥条目
        char[] keyPass = keyPassword.toCharArray();
        keyStore.setKeyEntry(alias, privateKey, keyPass, new Certificate[]{cert});

        // 保存到文件
        try (FileOutputStream fos = new FileOutputStream(jksPath)) {
            keyStore.store(fos, ksPassword);
        }

        System.out.println("JKS 文件已生成: " + jksPath);
    }

    public static void convertJksToPfx(String jksPath, String pfxPath, String jksPassword, String pfxPassword) throws Exception {

        // 1. 加载 JKS 文件
        KeyStore jksKeyStore = KeyStore.getInstance("JKS");
        char[] jksPass = jksPassword.toCharArray();

        try (FileInputStream fis = new FileInputStream(jksPath)) {
            jksKeyStore.load(fis, jksPass);
        }

        // 2. 创建 PKCS#12 KeyStore
        KeyStore pfxKeyStore = KeyStore.getInstance("PKCS12", "BC");
        char[] pfxPass = pfxPassword.toCharArray();
        pfxKeyStore.load(null, pfxPass);

        // 3. 复制所有条目
        Enumeration<String> aliases = jksKeyStore.aliases();
        while (aliases.hasMoreElements()) {
            String alias = aliases.nextElement();
            if (jksKeyStore.isKeyEntry(alias)) {
                PrivateKey key = (PrivateKey) jksKeyStore.getKey(alias, jksPass);
                Certificate[] certChain = jksKeyStore.getCertificateChain(alias);
                pfxKeyStore.setKeyEntry(alias, key, pfxPass, certChain);
            } else if (jksKeyStore.isCertificateEntry(alias)) {
                Certificate cert = jksKeyStore.getCertificate(alias);
                pfxKeyStore.setCertificateEntry(alias, cert);
            }
        }
        // 4. 保存 PFX 文件
        try (FileOutputStream fos = new FileOutputStream(pfxPath)) {
            pfxKeyStore.store(fos, pfxPass);
        }
        System.out.println("PFX 文件已生成: " + pfxPath);
    }

    public static void main(String[] args) throws Exception {
        String privateKeyPem = "-----BEGIN PRIVATE KEY-----" + "私钥字符串" + "-----END PRIVATE KEY-----";
        String certPem = "-----BEGIN CERTIFICATE-----" + "公钥字符串" + "-----END CERTIFICATE-----";
        // 生成JKS
        generateJksWithCert(privateKeyPem, certPem, "mykey", "keystore.jks", "changeit", "changeit");
        // JKS转换为PFX
        convertJksToPfx("C:\\Users\\sky\\Desktop\\keystore.jks", "C:\\Users\\sky\\Desktop\\k.pfx", "changeit", "260128");

    }


}
相关推荐
咩咩啃树皮7 小时前
第40篇:Vue3组件化开发精讲——组件拆分、复用、父子通信、工程化架构
java·前端·架构
灯澜忆梦7 小时前
GO_并发编程---定时器
开发语言·后端·golang
鱟鲥鳚7 小时前
Spring Boot 集成 LangChain4j:从模型调用到 Tool Calling(Demo版)
java·spring boot
-银雾鸢尾-7 小时前
C#中的StringBuilder相关方法
开发语言·c#
-银雾鸢尾-8 小时前
C#中结构体与类的区别;抽象类与接口的区别
开发语言·c#
大模型码小白8 小时前
【Python零基础教程】继承、多态与魔法函数:面向对象编程三大核心特性详解
java·大数据·开发语言·人工智能·python·ai编程
腾渊信息科技公司9 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
爱笑的源码基地10 小时前
高并发 Redis 缓存门诊HIS系统源码,含财务统计药房进销存
java·程序·门诊系统·诊所系统·云诊所源码
wuqingshun31415910 小时前
TCP超时重传机制是为了解决什么问题?
java
段一凡-华北理工大学10 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化