本文轉自:
數字證書簡介及Java編碼實作
CA認證原理以及實作
java CA憑證制作和代碼中使用
名詞大意
秘鑰庫:存儲了
公鑰
和
私鑰
資訊,一個秘鑰庫可以存儲
多對
的密鑰對(密鑰對可以了解為就是
數字證書
),通過alias别名來取出需要的密鑰對,存放于
伺服器
,
xxx.keystore
檔案
數字證書:隻能存儲
公鑰
,可以從
xxxx.keystore
中導出某個
密鑰對
的
公鑰證書
,存放于
用戶端
,
xxx.cer
檔案
java使用數字證書
Java 6提供了完善的數字證書管理實作,我們幾乎無需關注,僅通過操作
密鑰庫
和
數字證書
就可完成相應的
加密解密
和
簽名驗簽
過程。
密鑰庫
管理
私鑰
,
數字證書
管理
公鑰
,公鑰和私鑰分屬消息傳遞雙方,進行
加密消息傳遞
。
CertificateCoder工具類
/****
* 獲得私鑰,獲得私鑰後,通過RSA算方法實作進行"私鑰加密,公鑰解密"和"公鑰加密,私鑰解密"操作
* @param keyStorePath 密鑰庫路徑
* @param alias 别名
* @param keystore_password 秘鑰庫密碼
* @param ca_password 證書密碼
* @return 私鑰
*/
private static PrivateKey getPrivateKeyByKeyStore(String keyStorePath, String alias, String keystore_password,String ca_password)throws Exception{
//獲得密鑰庫
KeyStore ks = getKeyStore(keyStorePath,keystore_password);
//獲得私鑰
return (PrivateKey)ks.getKey(alias, ca_password.toCharArray());
}
/****
* 由Certificate獲得公鑰,獲得公鑰後,通過RSA算方法實作進行"私鑰加密,公鑰解密"和"公鑰加密,私鑰解密"操作
* @param certificatePath 證書路徑
* @return 公鑰
*/
private static PublicKey getPublicKeyByCertificate(String certificatePath)throws Exception {
//獲得證書
Certificate certificate = getCertificate(certificatePath);
//獲得公鑰
return certificate.getPublicKey();
}
/****
* 加載數字證書,JAVA 6僅支援x.509的數字證書
* @param certificatePath 證書路徑
* @return 證書
* @throws Exception
*/
private static Certificate getCertificate(String certificatePath) throws Exception{
//執行個體化證書工廠
CertificateFactory certificateFactory = CertificateFactory.getInstance("x.509");
//取得證書檔案流
FileInputStream in = new FileInputStream(certificatePath);
//生成證書
Certificate certificate = certificateFactory.generateCertificate(in);
//關閉證書檔案流
in.close();
return certificate;
}
/****
* 獲得Certificate
* @param keyStorePath 密鑰庫路徑
* @param alias 别名
* @param keystore_password 秘鑰庫密碼
* @return 證書
* @throws Exception
*/
private static Certificate getCertificate(String keyStorePath,String alias,String keystore_password) throws Exception{
//由密鑰庫獲得數字證書建構數字簽名對象
//獲得密鑰庫
KeyStore ks = getKeyStore(keyStorePath,keystore_password);
//獲得證書
return ks.getCertificate(alias);
}
/****
* 加載密鑰庫,加載了以後,我們就能通過相應的方法獲得私鑰,也可以獲得數字證書
* @param keyStorePath 密鑰庫路徑
* @param keystore_password 密碼
* @return 密鑰庫
* @throws Exception
*/
private static KeyStore getKeyStore(String keyStorePath,String keystore_password) throws Exception{
//執行個體化密鑰庫
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
//獲得密鑰庫檔案流
FileInputStream is = new FileInputStream(keyStorePath);
//加載密鑰庫
ks.load(is,keystore_password.toCharArray());
//關閉密鑰庫檔案流
is.close();
return ks;
}
/****
* 私鑰加密
* @param data 待加密的資料
* @param keyStorePath 密鑰庫路徑
* @param alias 别名
* @param keystore_password 秘鑰庫密碼
* @param ca_password 證書密碼
* @return 加密資料
* @throws Exception
*/
public static byte[] encryptByPriateKey(byte[] data,String keyStorePath,String alias,String keystore_password,String ca_password) throws Exception{
//獲得私鑰
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,keystore_password,ca_password);
//對資料加密
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,privateKey);
return cipher.doFinal(data);
}
/****
* 私鑰解密
* @param data 待解密資料
* @param keyStorePath 密鑰庫路徑
* @param alias 别名
* @param keystore_password 秘鑰庫密碼
* @param ca_password 證書密碼
* @return 解密資料
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data,String keyStorePath,String alias,String keystore_password,String ca_password) throws Exception{
//取得私鑰
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,keystore_password,ca_password);
//對資料解密
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE,privateKey);
return cipher.doFinal(data);
}
/****
* 公鑰加密
* @param data 等待加密資料
* @param certificatePath 證書路徑
* @return 加密資料
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data,String certificatePath) throws Exception{
//取得公鑰
PublicKey publicKey = getPublicKeyByCertificate(certificatePath);
//對資料加密
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
return cipher.doFinal(data);
}
/****
* 公鑰解密
* @param data 等待解密的資料
* @param certificatePath 證書路徑
* @return 解密資料
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data,String certificatePath)throws Exception{
//取得公鑰
PublicKey publicKey = getPublicKeyByCertificate(certificatePath);
//對資料解密
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/****
* @param sign 簽名
* @param keyStorePath 密鑰庫路徑
* @param alias 别名
* @param keystore_password 秘鑰庫密碼
* @param ca_password 證書密碼
* @return 簽名
* @throws Exception
*/
public static byte[] sign(byte[] sign,String keyStorePath,String alias,String keystore_password,String ca_password)throws Exception{
//獲得證書
X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath,alias,keystore_password);
//建構簽名,由證書指定簽名算法
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
//擷取私鑰
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,keystore_password,ca_password);
//初始化簽名,由私鑰建構
signature.initSign(privateKey);
signature.update(sign);
return signature.sign();
}
/****
* 驗證簽名
* @param data 資料
* @param sign 簽名
* @param certificatePath 證書路徑
* @return 驗證通過為真
* @throws Exception
*/
public static boolean verify(byte[] data,byte[] sign,String certificatePath) throws Exception{
//獲得證書
X509Certificate x509Certificate = (X509Certificate)getCertificate(certificatePath);
//由證書建構簽名
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
//由證書初始化簽名,實際上是使用了證書中的公鑰
signature.initVerify(x509Certificate);
signature.update(data);
return signature.verify(sign);
}
CertificateCoderTest測試類
/** 秘鑰庫密碼. */
private static final String keystore_password = "123456";
/** 證書密碼. */
private static final String ca_password = "111111";
/** 證書别名. */
private static final String alias = "ljw";
/** 密鑰庫檔案. */
private static final String keyStorePath = "F:\\Certifacate\\ljw.keystore";
/** 數字證書檔案. */
private static final String certificatePath = "F:\\Certifacate\\ljw.cer";
//我們假定密鑰庫檔案yale.keystore存儲在D盤根目錄,數字證書檔案yale.cer也存儲在D盤根目錄
/****
* 公鑰加密---私鑰解密
* @throws Exception
*/
@Test
public void test1() throws Exception{
System.err.println("公鑰加密---私鑰解密");
String inputStr = "數字證書";
byte[] data = inputStr.getBytes();
//公鑰加密
byte[] encrypt = CertificateCoder.encryptByPublicKey(data, certificatePath);
//私鑰解密
byte[] decrypt = CertificateCoder.decryptByPrivateKey(encrypt, keyStorePath, alias, keystore_password, ca_password);
String outputStr = new String(decrypt);
System.err.println("加密前:\n" + inputStr);
System.err.println("解密後:\n" + outputStr);
}
/****
* 私鑰加密---公鑰解密
* @throws Exception
*/
@Test
public void test2()throws Exception{
System.err.println("私鑰加密---公鑰解密");
String inputStr = "數字簽名";
byte[] data = inputStr.getBytes();
//私鑰加密
byte[] encodedData = CertificateCoder.encryptByPriateKey(data, keyStorePath, alias, keystore_password, ca_password);
//公鑰解密
byte[] decodeData = CertificateCoder.decryptByPublicKey(encodedData, certificatePath);
String outputStr = new String (decodeData);
System.err.println("加密前:\n" + inputStr);
System.err.println("解密後:\n" + outputStr);
}
@Test
public void testSign()throws Exception{
String inputStr = "簽名";
byte[] data = inputStr.getBytes();
System.err.println("私鑰簽名---公鑰驗證");
//産生簽名
byte[] sign = CertificateCoder.sign(data, keyStorePath, alias, keystore_password, ca_password);
System.err.println("簽名:\n" + sign);
//驗證簽名
boolean status = CertificateCoder.verify(data, sign, certificatePath);
System.err.println("狀态:\n " + status);
}