【4.证书和私钥,产生pfx证书】

本文详细介绍了如何使用私钥和公钥证书生成PFX证书,并提供了完整的Java代码示例,包括私钥和证书的读取、PFX证书的合成及从PFX中提取私钥和证书的过程。

题目要求:两张证书,分别有对应的公私钥对。

银行方:(A)--------------对应bankside1.cer

私钥:

MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIApSXeqcT3pKCBDKGpKqf+ByvrSdwMzDnmUb+6eVsms/GpbIhCHrGr+/fPRuq/COZuEsiNmkjusEeNgJCEoga/AzQ3xDklx6VZ7UDMfOVtK4KRsWHSMfYCtcXm2btppxcM6dOFwimtt1vPptgYfxsbdmtrxJw0ziccj0jAV4wpPAgMBAAECgYAHh+WMRZSv6aJ0+t1GGasRm4Pc5z8dDgP8uu8021MIOMUATuiahg5onyE3EYzhxQzziYGaOO3A2eSXMtAMrr+oCdwN7gqwjShgGkB/2cDvDnJ0wFHntvCYXjp13QEFJ8CO5fkYWLVxFtJ6VrdLUktUvhR+Fw4JLuTho/11lYdhGQJBAMFdi3RD2XEyoAoH4mkZ5siPfyW6gu5qkBBroAb3WJaAYxL0bwRmFYI+Q5YAmjYZwJlnm8AC3bMJREpFslP0NOUCQQCprNCXNQal6XuzyQGngy6eAOVGLKp/inGWyRW/wuFu6TJAGTAonbwTpNfeEfQ3aOJGgt/DHWOfvdVJ9BbraqMjAkEArX/2BRhsHrnCB74TVSK8hPDcsUms+af8I/+t0xJVFpWUUAmrI1NFsVuU4R8hP7HTstHYWm0359FEyS/IVrQkUQJAXaWG3t2iVLHf12OKaTTq5sPhxvBiDdCQTsOfIF5j474LQPtl7BTauBDUH7nTCz31HSugamTvFjxE2vNALyCE9wJAEE6G0W9IZDm6w+5nbiZ2mAhd0VBfMI2apa09/yMQGcqt2974bw/42chPoO9Vcwua+x3LsQ1stxl3+6jADQp7Fw==
公钥:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCAKUl3qnE96SggQyhqSqn/gcr60ncDMw55lG/unlbJrPxqWyIQh6xq/v3z0bqvwjmbhLIjZpI7rBHjYCQhKIGvwM0N8Q5JcelWe1AzHzlbSuCkbFh0jH2ArXF5tm7aacXDOnThcIprbdbz6bYGH8bG3Zra8ScNM4nHI9IwFeMKTwIDAQAB

 


银联云闪付方:(B)--------------对应leageside.cer
私钥:

MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIuJPMSnG7ve71SVj4FL6N+hfSnLufDZF3zKeTvuzKnTSuY9FDakJhZHafpQgqJ381gxmGw8Kz22EM5e29eEBCgeVF80TmdKzd4FjpIjksKTGrbAV9M4yXEgKxsQKe+yNrBveDQ9VRHpAcNo1dExvZi7HW1leOKvOrd2U1uOg9cRAgMBAAECgYBtM9iFJytDWvP/RJVs4VW9PwtPnItG/P+uwF8lEnzGJACoNAEPymOsZ/N+3Wd/c1TVHutlOam1wDli6UYwYrdE7l9gc5WYEDfu4jUJ/FJ9WX9f4qPqExHRwg6Ag72VADwf2CLAVZzbKTt4jlIv2BvBdPMraZ7C/kviXRA6QmJEYQJBAMYQ4RjcC6dLWhzxw1KBNrL2pY778aDu8pLCJxP/Bl4p0z5Mvh1kNS2xIAFyFq4Mwai3kpmiHh65L9rbNbl6Vg0CQQC0WajWWRL8w1DbkNugmfLBOLvh+C7Sj5JoeT3YD4QRNk0BFNGh0Q3lFBNodDgAmmv05YdHc2ZBRVebYGSWu+gVAkEAh7GatXBTn4qVMw1C9qxFsDggVqQu90Wc9ISFR0LJtwtKiP0Eppg3gpU9yx/Bf/6HUrJpgk25+ux+Z58U4Hx6pQJAVHVEhxTxumMxY5Gj+ML/lxMdkYYrTzojIz/cAWnKvFDEoQQB5BjFvAi5ygnbDBVFB0vSHVjigyCZFU9/68MVvQJARLRIskdXskm77Zk4pavc7Z05oAGjQ4jKsyzjPXp1bqeL3e9c5GdBB3/2zcAZiKY//WMkHEBhcaRcC9rrLr6G1g==
公钥:

MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLiTzEpxu73u9UlY+BS+jfoX0py7nw2Rd8ynk77syp00rmPRQ2pCYWR2n6UIKid/NYMZhsPCs9thDOXtvXhAQoHlRfNE5nSs3eBY6SI5LCkxq2wFfTOMlxICsbECnvsjawb3g0PVUR6QHDaNXRMb2Yux1tZXjirzq3dlNbjoPXEQIDAQAB

  题目目的:

           做一个小工具,输入参数为证书和私钥文件,输出pfx证书。

 

//  我自己写的程序 V1.0:读取 证书  和 私钥,获取pfx:

package test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;

import sun.misc.BASE64Decoder;

public class gen_pfx {
	/*
	 *  1. 导入 私钥信息,导入证书
	 *  2. 生成 keyStore,并保存
	 * */
	public static void main(String args[]) throws Exception {
		 	
		 String certPath = "C:\\Users\\Administrator\\Desktop\\ttt\\bankside1.pfx";
		 // 创建KeyStore
		 KeyStore store = KeyStore.getInstance("PKCS12");
		 store.load(null, null);
 
		// 导入私钥 
		String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIApSXeqcT3pKCBDKGpKqf+ByvrSdwMzDnmUb+6eVsms/GpbIhCHrGr+/fPRuq/COZuEsiNmkjusEeNgJCEoga/AzQ3xDklx6VZ7UDMfOVtK4KRsWHSMfYCtcXm2btppxcM6dOFwimtt1vPptgYfxsbdmtrxJw0ziccj0jAV4wpPAgMBAAECgYAHh+WMRZSv6aJ0+t1GGasRm4Pc5z8dDgP8uu8021MIOMUATuiahg5onyE3EYzhxQzziYGaOO3A2eSXMtAMrr+oCdwN7gqwjShgGkB/2cDvDnJ0wFHntvCYXjp13QEFJ8CO5fkYWLVxFtJ6VrdLUktUvhR+Fw4JLuTho/11lYdhGQJBAMFdi3RD2XEyoAoH4mkZ5siPfyW6gu5qkBBroAb3WJaAYxL0bwRmFYI+Q5YAmjYZwJlnm8AC3bMJREpFslP0NOUCQQCprNCXNQal6XuzyQGngy6eAOVGLKp/inGWyRW/wuFu6TJAGTAonbwTpNfeEfQ3aOJGgt/DHWOfvdVJ9BbraqMjAkEArX/2BRhsHrnCB74TVSK8hPDcsUms+af8I/+t0xJVFpWUUAmrI1NFsVuU4R8hP7HTstHYWm0359FEyS/IVrQkUQJAXaWG3t2iVLHf12OKaTTq5sPhxvBiDdCQTsOfIF5j474LQPtl7BTauBDUH7nTCz31HSugamTvFjxE2vNALyCE9wJAEE6G0W9IZDm6w+5nbiZ2mAhd0VBfMI2apa09/yMQGcqt2974bw/42chPoO9Vcwua+x3LsQ1stxl3+6jADQp7Fw==";
		RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) getPrivateKey(privateKey);
			
		// 导入证书
		CertificateFactory cf = CertificateFactory.getInstance("X.509");
		X509Certificate cert = (X509Certificate)cf.generateCertificate(new FileInputStream("C:\\Users\\Administrator\\Desktop\\ttt\\leageside.cer"));
		System.out.println(cert.toString());

	    // 生成keyStore
		store.setKeyEntry("Infosec", rsaPrivateKey,"123456".toCharArray(), new Certificate[] { cert });
		// 保存
		FileOutputStream fos =new FileOutputStream(certPath);
		store.store(fos, "123456".toCharArray());		
		fos.close();  
	}
	
	// 将string 转为 privateKey
	public static PrivateKey getPrivateKey(String key) throws Exception {
        byte[] keyBytes;
        keyBytes = (new BASE64Decoder()).decodeBuffer(key);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
  }
	
}

我认为有两大问题

1. 通过 私钥 和 证书可以任意的产生 pfx,就算不是匹配的私钥和证书都可以产生pfx证书,我认为可能是私钥对证书进行了加密,此处可能涉及到 证书链的东西。

2. 在对 私钥的获取中,我采用的是 字符串的形式获取,直接读取字符串,然后进行了类型强转:通过字符串转成 字节数组,再通过PKCS8EncodeedKeySpec的方式 转换,最后通过KeyFactory的方法以RSA的形式获取,再产生 私钥。可能不妥。

 

09/25 又在网上找了个文章,看了一下,发现差不太多.原来:

2. 在进行 私钥转换时,也是采用 字符串 BASE64编码,然后 keyFactory转换成私钥。rsaPrivateKey也是使用PKCS8的标准。后来看了下, pkcs8 是私钥的标准。

1. 至于使用到了 chain,

X509Certificate[] chain = { x509Certificate }; 

考虑可能是证书的一种表示形式,通过序列的形式表示出来。然后使用keyStore将 证书 和 私钥 合并起来,形成pfx。

 

对上面的程序进行了改进,就是排排版,看起来更顺眼一些。v2.0

package pfx;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Enumeration;

/**
 * Created by ssl on 2017/9/5.
 */
public class PFXUtils {

	
// 1. 根据 String  获取 私钥/ 公钥 对象------------------------------------------------------------	
	/**
     * 根据私钥Base64字符串获取私钥对象  
     *						1.  通过string 获取 字节数组
     * @param privateKeyStr
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
        byte[] privateKeyByte = Base64.decodeBase64(privateKeyStr);
        return getPrivateKey(privateKeyByte);
    }
    /**
     * 根据公钥base64字符串获取公钥
     *
     * @param publicKeyStr Base64编码后的公钥字节数组
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(String publicKeyStr) throws Exception {
        byte[] publicKeyByte = Base64.decodeBase64(publicKeyStr);
        return getPublicKey(publicKeyByte);
    }
	 /**
     * 根据私钥字节数组获取私钥对象
     *                   2. 通过字节数组获取 私钥
     * @param privateKeyByte
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKey(byte[] privateKeyByte) throws Exception {
        PrivateKey privateKey = null;
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);
        KeyFactory keyFactory = getKeyFactory();
        privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }
    
    /**
     * 根据公钥字节数组获取公钥
     *
     * @param publicKeyByte 公钥字节数组
     * @return
     * @throws Exception
     */
    public static PublicKey getPublicKey(byte[] publicKeyByte) throws Exception {
        PublicKey publicKey = null;
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByte);
        KeyFactory keyFactory = getKeyFactory();
        publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }
    	 
    /**
     * 获取RSA算法的keyFactory
     *                  3. 指定使用的算法
     * @return
     */
    private static KeyFactory getKeyFactory() throws Exception {
        return getKeyFactory("RSA");
    }

    /**
     * 获取指定算法的keyFactory :操作与 密钥有关
     *
     * @param algorithm
     * @return
     */
    private static KeyFactory getKeyFactory(String algorithm) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        return keyFactory;
    }
 
    
 //   2. 根据证书获得 私钥------------------------------------------------------- ----------------  
    /**
     * 根据pfx证书得到私钥
     *                1. 获取证书数据
     * @param pfxPath
     * @param password
     * @return
     * @throws Exception
     */
    public static PrivateKey getPrivateKeyByPfx(String pfxPath, String password) throws Exception {
        File pfxFile = new File(pfxPath);
        return getPrivateKeyByPfx(FileUtils.readFileToByteArray(pfxFile), password);
    }
    
    /**
     * 根据pfx证书得到私钥
     *                 2. 获取 私钥,需要先获取 keystore
     * @param pfxData
     * @param password
     * @throws Exception
     */
    public static PrivateKey getPrivateKeyByPfx(byte[] pfxData, String password) throws Exception {
        PrivateKey privateKey = null;
        KeyStore keystore = getKeyStore(pfxData, password); 
        Enumeration<String> enums = keystore.aliases();
        String keyAlias = "";
        while (enums.hasMoreElements()) {
            keyAlias = enums.nextElement();
            if (keystore.isKeyEntry(keyAlias)) {
                privateKey = (PrivateKey) keystore.getKey(keyAlias, password.toCharArray());
            }
        }
        return privateKey;
    }
    
    
    /**
     * 根据pfx证书获取keyStore : 跟证书操作有关的东西,类似于 证书条目记录
     *                    3. 获取证书中的 keystore
     * @param pfxData
     * @param password
     * @return
     * @throws Exception
     */
    private static KeyStore getKeyStore(byte[] pfxData, String password) throws Exception {
        KeyStore keystore = KeyStore.getInstance("PKCS12");
        keystore.load(new ByteArrayInputStream(pfxData), password.toCharArray());
        return keystore;
    }
    
//3.根据pfx证书获取证书对象 ------------------------------------------------------------------------------------------------------
    /**
     * 根据pfx证书获取证书对象
     *
     * @param pfxPath  pfx证书路径
     * @param password pfx证书密码
     * @return
     * @throws Exception
     */
    public static X509Certificate getX509Certificate(String pfxPath, String password) throws Exception {
        File pfxFile = new File(pfxPath);
        return getX509Certificate(FileUtils.readFileToByteArray(pfxFile), password);
    }
    
    /**
     * 根据pfx证书获取证书对象
     *
     * @param pfxData  pfx的字节数组
     * @param password pfx证书密码
     * @return
     * @throws Exception
     */
    public static X509Certificate getX509Certificate(byte[] pfxData, String password) throws Exception {
        X509Certificate x509Certificate = null;
        KeyStore keystore = getKeyStore(pfxData, password);
        Enumeration<String> enums = keystore.aliases();
        String keyAlias = "";
        while (enums.hasMoreElements()) {
            keyAlias = enums.nextElement();
            if (keystore.isKeyEntry(keyAlias)) {
                x509Certificate = (X509Certificate) keystore.getCertificate(keyAlias);
            }
        }
        return x509Certificate;
    }

   
//4. 根据私钥、公钥证书、密码生成pkcs12,生成 pfx证书------------------------------------------------------------------------------------------------------------------

    /**
     * 根据私钥、公钥证书、密码生成pkcs12
     *
     * @param privateKey      私钥
     * @param x509Certificate 公钥证书
     * @param password        需要设置的密钥
     * @return
     * @throws Exception
     */
    public static byte[] generatorPkcx12(PrivateKey privateKey, X509Certificate x509Certificate, String password)
            throws Exception {
        Certificate[] chain = {x509Certificate};
        KeyStore keystore = KeyStore.getInstance("PKCS12");
        keystore.load(null, password.toCharArray());
        keystore.setKeyEntry(x509Certificate.getSerialNumber().toString(), privateKey, password.toCharArray(), chain);
        ByteArrayOutputStream bytesos = new ByteArrayOutputStream();
        keystore.store(bytesos, password.toCharArray());
        byte[] bytes = bytesos.toByteArray();
        return bytes;
    }

    /**
     * 根据私钥、公钥证书、密钥,保存为pfx文件
     *
     * @param privateKey      私钥
     * @param x509Certificate 公钥证书
     * @param password        打开pfx的密钥
     * @param saveFile        保存的文件
     * @return
     * @throws Exception
     */
    public static String generatorPFX(PrivateKey privateKey, X509Certificate x509Certificate, String password, File
            saveFile) throws Exception {
        //判断文件是否存在
        if (!saveFile.exists()) {
            //判断文件的目录是否存在
            if (!saveFile.getParentFile().exists()) {
                saveFile.getParentFile().mkdirs();
            }
            saveFile.createNewFile();
        }
        byte[] pkcs12Byte = generatorPkcx12(privateKey, x509Certificate, password);
        FileUtils.writeByteArrayToFile(saveFile, pkcs12Byte);
        return saveFile.getPath();
    }

    
    public static void main(String[] args) throws Exception {
        String pfxPath = "C:\\Users\\49383\\Desktop\\文件\\国新测试证书-1.pfx";
        String password = "1";
        //私钥:pfx文件中获取私钥对象
        PrivateKey privateKey = getPrivateKeyByPfx(pfxPath, password);
        byte[] privateKeyByte = privateKey.getEncoded();
        String privateKeyStr = Base64.encodeBase64String(privateKeyByte);
        System.out.println("私钥Base64字符串:" + privateKeyStr);
        //=====私钥Base64字符串转私钥对象
        PrivateKey privateKey2 = getPrivateKey(privateKeyStr);
        System.out.println("私钥Base64字符串2:" + Base64.encodeBase64String(privateKey2.getEncoded()));
        //证书:从pfx文件中获取证书对象
        X509Certificate certificate = getX509Certificate(pfxPath, password);
        System.out.println("证书主题:" + certificate.getSubjectDN().getName());
        String publicKeyStr = Base64.encodeBase64String(certificate.getPublicKey().getEncoded());
        System.out.println("公钥Base64字符串:" + publicKeyStr);
        //=====根据公钥Base64字符串获取公钥对象
        System.out.println("公钥Base64字符串2:" + Base64.encodeBase64String(getPublicKey(publicKeyStr).getEncoded()));
        //PFX:合成pfx(需要私钥、公钥证书)
        String savePath = generatorPFX(privateKey, certificate, "1", new File
                ("C:\\Users\\49383\\Desktop\\文件\\009\\009.pfx"));
        System.out.println(savePath);
    }
}



 

完整的 pfx 和 keystore 和 私钥 证书 之间的转换关系:

package pfx;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;


/**
 *  1. pfx 是什么?
 *       pfx  是带有  私钥的证书文件,是符合 pkcs12标准的证书文件。
 *  2. keystore是什么 ? 
 *       keystore 是 类似于证书库的存在,记录一条证书的信息,可以通过 指定算法,序列号、私钥、证书来产生。
 *  3. 跟 chain  有什么关系 ?
 *        还不清楚???
 *       
 * @author Administrator
 *
 */
public class Gen_pfx {
	/**
	 *  1. 获取 私钥  ------ 通过字符串经过 BASE64编码成 字节数组,然后通过 KeyFactory 转换成私钥
	 *  2. 获取 证书------- 通过 CertificateFactory 获取
	 *  3. 获取 keystore------- 通过指定的属性值来生成
	 *  4. 生成 pfx 证书 
	 *   
	 * @param args
	 * @throws Exception
	 */
	  public static void main(String[] args) throws Exception {
	      
	        //=====私钥Base64字符串转私钥对象
	        PrivateKey privateKey2 = getPrivateKey("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIApSXeqcT3pKCBDKGpKqf+ByvrSdwMzDnmUb+6eVsms/GpbIhCHrGr+/fPRuq/COZuEsiNmkjusEeNgJCEoga/AzQ3xDklx6VZ7UDMfOVtK4KRsWHSMfYCtcXm2btppxcM6dOFwimtt1vPptgYfxsbdmtrxJw0ziccj0jAV4wpPAgMBAAECgYAHh+WMRZSv6aJ0+t1GGasRm4Pc5z8dDgP8uu8021MIOMUATuiahg5onyE3EYzhxQzziYGaOO3A2eSXMtAMrr+oCdwN7gqwjShgGkB/2cDvDnJ0wFHntvCYXjp13QEFJ8CO5fkYWLVxFtJ6VrdLUktUvhR+Fw4JLuTho/11lYdhGQJBAMFdi3RD2XEyoAoH4mkZ5siPfyW6gu5qkBBroAb3WJaAYxL0bwRmFYI+Q5YAmjYZwJlnm8AC3bMJREpFslP0NOUCQQCprNCXNQal6XuzyQGngy6eAOVGLKp/inGWyRW/wuFu6TJAGTAonbwTpNfeEfQ3aOJGgt/DHWOfvdVJ9BbraqMjAkEArX/2BRhsHrnCB74TVSK8hPDcsUms+af8I/+t0xJVFpWUUAmrI1NFsVuU4R8hP7HTstHYWm0359FEyS/IVrQkUQJAXaWG3t2iVLHf12OKaTTq5sPhxvBiDdCQTsOfIF5j474LQPtl7BTauBDUH7nTCz31HSugamTvFjxE2vNALyCE9wJAEE6G0W9IZDm6w+5nbiZ2mAhd0VBfMI2apa09/yMQGcqt2974bw/42chPoO9Vcwua+x3LsQ1stxl3+6jADQp7Fw==");
	        System.out.println("私钥Base64字符串2:" + Base64.encodeBase64String(privateKey2.getEncoded()));
	        
	        // ===导入证书数据
	        CertificateFactory cf = CertificateFactory.getInstance("X.509");
			X509Certificate certificate = (X509Certificate)cf.generateCertificate(new FileInputStream("C:\\Users\\Administrator\\Desktop\\ttt\\bankside1.cer"));
	        
	        //PFX:合成pfx(需要私钥、公钥证书)
	        String savePath = generatorPFX(privateKey2, certificate, "123456", new File("C:\\Users\\Administrator\\Desktop\\ttt\\bankside2501.pfx"));
	        System.out.println(savePath);
	    }  
	   /**
	     * 根据私钥Base64字符串获取私钥对象
	     * @param privateKeyStr
	     * @return
	     * @throws Exception
	     */
	  public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
	      byte[] privateKeyByte = Base64.decodeBase64(privateKeyStr);
	      return getPrivateKey(privateKeyByte);
	  }
	  /**
	     * 根据私钥字节数组获取私钥对象
	     * @param privateKeyByte
	     * @return
	     * @throws Exception
	     */
	    public static PrivateKey getPrivateKey(byte[] privateKeyByte) throws Exception {
	        PrivateKey privateKey = null;
	        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);
	        KeyFactory keyFactory = getKeyFactory("RSA");
	        privateKey = keyFactory.generatePrivate(keySpec);
	        return privateKey;
	    }
	  /**
	   * 获取指定算法的keyFactory
	   * @param algorithm
	   * @return
	   */
	 private static KeyFactory getKeyFactory(String algorithm) throws Exception {
	     KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
	     return keyFactory;
	 }
    /**
     * 根据私钥、公钥证书、密码生成pkcs12
     *
     * @param privateKey      私钥
     * @param x509Certificate 公钥证书
     * @param password        需要设置的密钥
     * @return
     * @throws Exception
     */
    public static byte[] generatorPkcx12(PrivateKey privateKey, X509Certificate x509Certificate, String password)
            throws Exception {
        Certificate[] chain = {x509Certificate};
        KeyStore keystore = KeyStore.getInstance("PKCS12");
        keystore.load(null, password.toCharArray());
        keystore.setKeyEntry(x509Certificate.getSerialNumber().toString(), privateKey, password.toCharArray(), chain);
        ByteArrayOutputStream bytesos = new ByteArrayOutputStream();
        keystore.store(bytesos, password.toCharArray());
        byte[] bytes = bytesos.toByteArray();
        return bytes;
    }
    /**
     * 根据私钥、公钥证书、密钥,保存为pfx文件
     *
     * @param privateKey      私钥
     * @param x509Certificate 公钥证书
     * @param password        打开pfx的密钥
     * @param saveFile        保存的文件
     * @return
     * @throws Exception
     */
    public static String generatorPFX(PrivateKey privateKey, X509Certificate x509Certificate, String password, File
            saveFile) throws Exception {
        //判断文件是否存在
        if (!saveFile.exists()) {
            //判断文件的目录是否存在
            if (!saveFile.getParentFile().exists()) {
                saveFile.getParentFile().mkdirs();
            }
            saveFile.createNewFile();
        }
        byte[] pkcs12Byte = generatorPkcx12(privateKey, x509Certificate, password);
        FileUtils.writeByteArrayToFile(saveFile, pkcs12Byte);
        return saveFile.getPath();
    }
}




 

然后花了个 流程图,方便记忆:

 

明天再补充。

 

 

 

 

 

 

<think> 我们正在处理用户关于将PFX文件转换为PEM格式的问题。用户明确询问在Windows系统上的转换方法。 根据引用,我们知道: - PFX文件通常包含证书私钥,并且可能有一个提取密码。 - 使用OpenSSL工具可以完成转换。 步骤: 1. 安装OpenSSL:用户需要先安装OpenSSL。如果尚未安装,请用户下载(例如从Slproweb.com下载Win64 OpenSSL)。 2. 打开命令提示符(以管理员身份运行,但通常不需要,除非安装到系统目录)。 3. 使用命令进行转换。 注意:引用[4]提供了转换命令: openssl pkcs12 -in xxxx.pfx -nodes -out server.pem 这个命令会将PFX文件转换为一个PEM文件,其中包含证书私钥。 但是,用户可能希望得到分开的证书私钥文件(如引用[1]所述),因此我们也可以提供分开的方法。 根据用户需求,有两种情况: 情况一:只生成一个包含所有内容(证书私钥)的PEM文件。 情况二:分别生成证书文件(.crt或.cer)私钥文件(.key)。 另外,引用[2][4]还提供了其他命令,例如: - 提取私钥:openssl rsa -in server.pem -out server.key - 提取证书:openssl x509 -in server.pem -out server.crt 但注意,如果已经通过第一个命令生成了server.pem(包含所有内容),那么我们可以从这个文件中手动分割,或者用命令提取。 因此,我们可以提供两种方法。 方法一:直接转换成一个PEM文件(包含私钥证书) 方法二:分别生成私钥证书文件(可能还包括CA证书) 我们按照步骤来写: 方法一:生成一个PEM文件 1. 打开命令提示符(CMD)并切换到PFX文件所在目录。 2. 执行命令:`openssl pkcs12 -in yourfile.pfx -nodes -out full.pem` 其中,`yourfile.pfx`替换为你的PFX文件名,`full.pem`是输出的PEM文件名。 执行过程中会提示输入导入密码(即PFX文件的提取密码)。 方法二:分别生成私钥证书CA证书(如果有的话) 步骤1:生成一个包含私钥证书的PEM文件(同方法一) 步骤2:从这个PEM文件中分离私钥证书。 提取私钥:`openssl rsa -in full.pem -out private.key` 提取证书:`openssl x509 -in full.pem -out certificate.crt` 注意:如果还有CA证书,可能需要手动打开full.pem文件,将CA证书部分(从第二个-----BEGIN CERTIFICATE-----开始到结束)复制到新文件(如ca.crt)中。 但是,引用[4]提供了另一种直接生成分开文件的方法: 提取证书(不包含私钥):`openssl pkcs12 -in xxxx.pfx -clcerts -nokeys -out key.cert` 提取私钥:`openssl pkcs12 -in xxxx.pfx -nocerts -out key.pem` 注意:这个私钥是加密的,如果不要加密,则加`-nodes`参数 所以我们可以这样写: 更推荐的方法(直接提取): 1. 提取证书(不包含私钥): openssl pkcs12 -in yourfile.pfx -clcerts -nokeys -out certificate.pem 2. 提取私钥(不加密): openssl pkcs12 -in yourfile.pfx -nocerts -nodes -out private.key 3. 如果还有CA证书(链): openssl pkcs12 -in yourfile.pfx -cacerts -nokeys -chain -out ca.pem 但是注意,上述命令执行时都会要求输入PFX文件的密码。 因此,我们综合给出步骤: 步骤1:安装OpenSSL for Windows(如果未安装)。 步骤2:打开命令提示符,进入PFX文件所在目录。 步骤3:分别执行以下三个命令(如果只需要证书私钥,则执行前两个): 1. 提取证书:`openssl pkcs12 -in yourfile.pfx -clcerts -nokeys -out certificate.pem` 2. 提取私钥:`openssl pkcs12 -in yourfile.pfx -nocerts -nodes -out private.key` 3. 提取CA证书:`openssl pkcs12 -in yourfile.pfx -cacerts -nokeys -chain -out ca.pem` 注意:执行过程中会要求输入PFX文件的密码(即导出时设置的密码)。 这样我们就得到了: - 服务器证书:certificate.pem - 私钥:private.key - CA证书链:ca.pem(如果有的话) 另外,引用[4]中还提到了将.cer转换为.pem的方法(但用户需求是PFX转PEM,所以不需要)。 我们还要注意:生成的private.key文件已经是PEM格式(文本格式,以-----BEGIN PRIVATE KEY-----开头),可以直接使用。 因此,回答如下: </think>### Windows 系统将 PFX 文件转换为 PEM 证书的方法 在 Windows 系统中,您可以使用 OpenSSL 工具将服务器的私钥 PFX 文件转换为 PEM 格式证书。以下是详细操作步骤: --- #### 方法一:完整转换(推荐) 1. **安装 OpenSSL** - 下载 Windows 版 OpenSSL:[slproweb.com/products/Win32OpenSSL.html](https://slproweb.com/products/Win32OpenSSL.html) - 安装时勾选 `Copy OpenSSL DLLs to /bin directory`(重要) 2. **打开命令提示符** - 按 `Win+R` 输入 `cmd` → 右键选择 **"以管理员身份运行"** 3. **执行转换命令** ```powershell # 转换 PFX 为包含完整证书链的 PEM openssl pkcs12 -in "C:\path\to\your.pfx" -nodes -out "C:\path\to\full_cert.pem" ``` - `-in`:指定输入 PFX 文件路径 - `-nodes`:禁止加密私钥(输出未加密的 PEM) - `-out`:指定输出 PEM 文件路径 - 执行后会提示输入 PFX 文件的提取密码[^2][^4] 4. **分离证书私钥** ```powershell # 提取证书部分(公钥) openssl x509 -in "C:\path\to\full_cert.pem" -out "C:\path\to\certificate.pem" # 提取私钥部分 openssl rsa -in "C:\path\to\full_cert.pem" -out "C:\path\to\private.key" ``` --- #### 方法二:直接分离转换 ```powershell # 直接提取证书(不含私钥) openssl pkcs12 -in "C:\path\to\your.pfx" -clcerts -nokeys -out "C:\path\to\cert.pem" # 直接提取私钥(未加密) openssl pkcs12 -in "C:\path\to\your.pfx" -nocerts -nodes -out "C:\path\to\private.key" ``` - `-clcerts`:仅提取客户端证书 - `-nokeys`:不包含私钥 - `-nocerts`:不包含证书[^1][^4] --- ### 关键注意事项 1. **密码安全** - PFX 文件通常有提取密码,执行命令时需输入(输入时不会显示字符) - 若需加密私钥,移除 `-nodes` 参数并设置密码: ```powershell openssl rsa -aes256 -in private.key -out encrypted.key ``` 2. **文件验证** - 用记事本打开 PEM 文件,确认包含以下标识: ``` -----BEGIN CERTIFICATE----- # 证书 -----BEGIN PRIVATE KEY----- # 私钥 ``` 3. **格式区别** | 文件类型 | 内容 | 编码方式 | |----------|---------------------|---------------| | .pfx | 证书+私钥+密码保护 | DER(二进制) | | .pem | 证书私钥 | Base64 文本 | | .key | 私钥 | Base64 文本 [^3] | 4. **常见错误处理** - **"Unable to load private key"**:检查 PFX 密码是否正确 - **"No certificate matches private key"**:使用 `-legacy` 参数兼容旧格式 - **文件路径错误**:建议将文件放在 `C:\OpenSSL\bin` 目录操作 --- ### 转换结果验证 ```powershell # 查看 PEM 证书信息 openssl x509 -in certificate.pem -text -noout # 验证私钥证书匹配 openssl rsa -in private.key -check ``` 成功匹配的特征:证书私钥的 modulus(模数)值相同 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值