1. 程式人生 > >KeyStore載入PublicKey/PrivateKey(公/私鑰)證書

KeyStore載入PublicKey/PrivateKey(公/私鑰)證書

開發過程中,對於簽名和驗籤的問題,相信大家沒少見過。很多時候,我們只是拿來就用,根本沒留意裡面的邏輯;

要麼就是專案現有的簽名和驗籤邏輯,要麼就是拿demo裡面的程式碼然後整合到專案中去,直接使用。

很少有自己去寫一套簽名和驗籤的程式碼邏輯,沒有完全理解透徹之前,總覺得簽名和驗籤神神祕祕高深的樣子;

當你讀透了裡面的程式碼邏輯之後,發現整個相當簡單,目前幾個專案中都有簽名和驗籤的公私鑰證書,今天有空就把它分享一下:

1、PublicKey 公鑰、PrivateKey 私鑰、KeyStore 身份驗證等名詞解釋和原理介紹

  • PublicKey 公鑰

     顧名思義,是在簽名和驗簽過程,驗籤所使用的公鑰證書。公鑰證書驗籤是不需要密碼的,這裡存在2個使用者角色物件:A/B;

A和B分別有一套公私鑰證書,那麼站在A的角度上來說,想要使用證書實現A/B之間的安全協議通訊:A持有的是A自己的私鑰證書,和B的公鑰證書;B持有的是B自己的私鑰證書和A的公鑰證書。通訊中:A向B傳送請求,那麼A持有A自己的私鑰進行簽名,B持有A的公鑰進行驗籤。相反同理

公私鑰證書對比圖
A持有 配對 B持有 方式
A—PrivateKey <——> A—PublicKey 簽名/驗籤
B—PublicKey <——> B—PrivateKey 驗籤/簽名
       
  • PrivateKey 私鑰

      同理,私鑰證書就是用來簽名的,私鑰證書籤名的時候一般都攜帶密碼,和簽名演算法等;比如對稱加密演算法:AES,DES等,非對稱加密演算法:RSA、D-H等。具體看各自專案使用情況。

  • KeyStore

        Keystone(OpenStack Identity Service)是OpenStack框架中,負責身份驗證、服務規則和服務令牌的功能, 它實現了OpenStack的IdentityAPI。Keystone類似一個服務匯流排, 或者說是整個Openstack框架的登錄檔, 其他服務通過keystone來註冊其服務的Endpoint(服務訪問的URL),任何服務之間相互的呼叫, 需要經過Keystone的身份驗證, 來獲得目標服務的Endpoint來找到目標服務。

        它是證書籤名和驗簽過程,必須都要用到的一個身份驗證的標識功能,好比公鑰證書和私鑰證書必須有一個裁判中間人來證明你們這對證書是合法且一致的。

程式碼如下:

package test;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;

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

//將私鑰檔案,公鑰檔案轉換成PrivateKey,PublicKey物件或獲取公私鑰內容
//僅供參考,不提供效能,bug等問題保障

public class LoadCertUtil {
	public static PrivateKey getPriKey(KeyStore keyStore,String password){
		try {
			Enumeration<String> aliasenum  = keyStore.aliases();
			if (aliasenum.hasMoreElements()) {
				String keyAlias = aliasenum.nextElement();
				if (keyStore.isKeyEntry(keyAlias)) {
					PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias,password.toCharArray());
					return privateKey;
				}
			}
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} catch (UnrecoverableKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static PublicKey getPubKey(KeyStore keyStore){
		try {
			Enumeration<String> aliasenum = keyStore.aliases();
			String keyAlias = null;
			if (aliasenum.hasMoreElements()) {
				keyAlias = aliasenum.nextElement();
				if (keyStore.isKeyEntry(keyAlias)) {
					X509Certificate  x509Certificate = (X509Certificate) keyStore.getCertificate(keyAlias);
					PublicKey publicKey = x509Certificate.getPublicKey();
					return publicKey;
				}
			}
		  } catch (KeyStoreException e) {
			  e.printStackTrace();
		  }
		return null;
	}
	
	
	public static KeyStore loadKeyStore(String pfxkeyfile,String password){
		System.out.println("載入簽名證書==>" + pfxkeyfile);
		FileInputStream fis = null;
		try {
			KeyStore keyStore = KeyStore.getInstance("PKCS12");
			fis = new FileInputStream(pfxkeyfile);
			char[] nPassword = password.toCharArray();
			if (null != keyStore) {
				keyStore.load(fis, nPassword);
			}
			return keyStore;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(null!=fis)
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return null;
	}
	
	public static PublicKey loadPubkey(String pubkeyfile){
		System.out.println("載入驗簽證書==>" + pubkeyfile);
		CertificateFactory cf = null;
		FileInputStream in = null;
		try {
			cf = CertificateFactory.getInstance("X.509");
			in = new FileInputStream(pubkeyfile);
			X509Certificate validateCert = (X509Certificate) cf.generateCertificate(in);
			return validateCert.getPublicKey();
		}catch (CertificateException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static void main(String[] args) {
		String pfxkeyfile ="D:\\certs\\allcerts\\00010000new2048.pfx";
		String password = "000000";
		String pubkeyfile ="D:\\certs\\acp_test_verify_sign.cer";
		
		KeyStore keyStore = loadKeyStore(pfxkeyfile,password);
		PrivateKey privateKey = getPriKey(keyStore,password);
		System.out.println("簽名私鑰-私鑰內容:" + Base64.encodeBase64String(privateKey.getEncoded()));
		PublicKey priPublicKey = getPubKey(keyStore);
		System.out.println("簽名私鑰-公鑰內容:"+Base64.encodeBase64String(priPublicKey.getEncoded()));
		
		PublicKey publicKey = loadPubkey(pubkeyfile);
		System.out.println("公鑰內容:"+Base64.encodeBase64String(publicKey.getEncoded()));
	}
}