1. 程式人生 > >【4.證書和私鑰,產生pfx證書】

【4.證書和私鑰,產生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();
    }
}




然後花了個 流程圖,方便記憶:

明天再補充。