1. 程式人生 > 實用技巧 >數字證書相關原始碼實現

數字證書相關原始碼實現

package com.albedo.security;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; public class MyCertifacate { private static final String STORE_PASS = "123456"; private static
final String ALIAS = "myCertificate"; private static final String KEYSTORE_PATH = "/Users/wangzhangxiong/myKeystore.keystore"; private static final String CERT_PATH = "/Users/wangzhangxiong/myCer.cer"; private static final String PLAIN_TEXT = "MANUTD is the most greatest club in the world."; /** X.509標準的證書 */ private static final String CERT_TYPE = "X.509"; public static void main(String[] args) throws IOException { /** * 假設現在有這樣一個場景 。A機器上的資料,需要加密匯出,然後將匯出檔案放到B機器上匯入。 在這個場景中,A相當於伺服器,B相當於客戶端 */ /** A */ KeyStore keyStore = getKeyStore(STORE_PASS, KEYSTORE_PATH); PrivateKey privateKey = getPrivateKey(keyStore, ALIAS, STORE_PASS); X509Certificate certificate = getCertificateByKeystore(keyStore, ALIAS); /** 加密和簽名 */ byte[] encodedText = encode(PLAIN_TEXT.getBytes(), privateKey); byte[] signature = sign(certificate, privateKey, PLAIN_TEXT.getBytes()); /** 現在B收到了A的密文和簽名,以及A的可信任證書 */ X509Certificate receivedCertificate = getCertificateByCertPath( CERT_PATH, CERT_TYPE); PublicKey publicKey = getPublicKey(receivedCertificate); byte[] decodedText = decode(encodedText, publicKey); System.out.println("Decoded Text : " + new String(decodedText)); System.out.println("Signature is : " + verify(receivedCertificate, decodedText, signature)); } /** * 載入金鑰庫,與Properties檔案的載入類似,都是使用load方法 * * @throws IOException */ public static KeyStore getKeyStore(String storepass, String keystorePath) throws IOException { InputStream inputStream = null; try { KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); inputStream = new FileInputStream(keystorePath); keyStore.load(inputStream, storepass.toCharArray()); return keyStore; } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (null != inputStream) { inputStream.close(); } } return null; } /** * 獲取私鑰 * * @param keyStore * @param alias * @param password * @return */ public static PrivateKey getPrivateKey(KeyStore keyStore, String alias, String password) { try { return (PrivateKey) keyStore.getKey(alias, password.toCharArray()); } catch (UnrecoverableKeyException | KeyStoreException | NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 獲取公鑰 * * @param certificate * @return */ public static PublicKey getPublicKey(Certificate certificate) { return certificate.getPublicKey(); } /** * 通過金鑰庫獲取數字證書,不需要密碼,因為獲取到Keystore例項 * * @param keyStore * @param alias * @return */ public static X509Certificate getCertificateByKeystore(KeyStore keyStore, String alias) { try { return (X509Certificate) keyStore.getCertificate(alias); } catch (KeyStoreException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 通過證書路徑生成證書,與載入金鑰庫差不多,都要用到流。 * * @param path * @param certType * @return * @throws IOException */ public static X509Certificate getCertificateByCertPath(String path, String certType) throws IOException { InputStream inputStream = null; try { // 例項化證書工廠 CertificateFactory factory = CertificateFactory .getInstance(certType); // 取得證書檔案流 inputStream = new FileInputStream(path); // 生成證書 Certificate certificate = factory.generateCertificate(inputStream); return (X509Certificate) certificate; } catch (CertificateException | IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (null != inputStream) { inputStream.close(); } } return null; } /** * 從證書中獲取加密演算法,進行簽名 * * @param certificate * @param privateKey * @param plainText * @return */ public static byte[] sign(X509Certificate certificate, PrivateKey privateKey, byte[] plainText) { /** 如果要從金鑰庫獲取簽名演算法的名稱,只能將其強制轉換成X509標準,JDK 6只支援X.509型別的證書 */ try { Signature signature = Signature.getInstance(certificate .getSigAlgName()); signature.initSign(privateKey); signature.update(plainText); return signature.sign(); } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 驗籤,公鑰包含在證書裡面 * * @param certificate * @param decodedText * @param receivedignature * @return */ public static boolean verify(X509Certificate certificate, byte[] decodedText, final byte[] receivedignature) { try { Signature signature = Signature.getInstance(certificate .getSigAlgName()); /** 注意這裡用到的是證書,實際上用到的也是證書裡面的公鑰 */ signature.initVerify(certificate); signature.update(decodedText); return signature.verify(receivedignature); } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { // TODO Auto-generated catch block e.printStackTrace(); } return false; } /** * 加密。注意金鑰是可以獲取到它適用的演算法的。 * * @param plainText * @param privateKey * @return */ public static byte[] encode(byte[] plainText, PrivateKey privateKey) { try { Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(plainText); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 解密,注意金鑰是可以獲取它適用的演算法的。 * * @param encodedText * @param publicKey * @return */ public static byte[] decode(byte[] encodedText, PublicKey publicKey) { try { Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(encodedText); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }