java提供了完整的密碼學API,我們可以結合密碼學相關的概念來系統的學習這些API。
1.密碼學簡介(crypto)
密碼學通俗來說就是研究如何對信息進行加密和破密,如果不是專門研究信息安全,通常我們只需學習和使用加密的方法,所以破密的相關知識我們可以忽略。
2.加密(Encrypt)
單以加密來說,密碼學可以分為經典密碼學和現代密碼學,經典密碼學的重點在於加密算法,利用移位,替換等方法對信息進行加密,一旦算法被人破譯那么信息就會泄露。而現代密碼學則不同,現代密碼學的安全性是基於密鑰,算法反而是公開的。根據密鑰的不同,現代密碼學可以分為對稱加密和非對稱加密,顧名思義,對稱加密就是通訊雙方使用同一對密鑰,而非對稱加密則是雙方都擁有一對私鑰和公鑰,私鑰自己保存而公鑰可以對外交換。這樣就可以避免對稱加密在密鑰交換時泄漏的風險。
3.信息摘要(Message Digest)
把任意長度的信息壓縮成固定長度,在密碼學上把經過hash算法計算壓縮后的數據稱為信息摘要。我們可以通過對比接收到的信息摘要來檢驗數據的完整性,防止數據在傳輸過程中被篡改。信息摘要的重點其實就是hash算法。
4.數據簽名(signature)
要驗證數據的完整性,只有信息摘要還是不夠的。因為如果攻擊者猜測到生成的信息摘要使用的是哪種hash算法(畢竟hash算法其實就MD5,SHA-1那幾種),那么攻擊者可以篡改信息后,重新生成信息摘要,所以還需要對信息摘要進行加密。數據簽名其實可以理解為信息摘要和非對稱加密的結合體。
5.Java安全體系
Java 安全體系 API 分為四部分:JCA、JCE、JSSE 和 JAAS。
JCA:Java API 提供基本的加密框架,比如證書、數字簽名、消息摘要和密鑰產生器。
JCE:是 JCA 的擴展,提供各種算法的實現、密鑰管理等功能,主要位於 javax.crypto 及子包中。
JSSE:是 Java 安全套接字擴展的縮寫,主要提供基於 SSL 安全網絡通信的 API。
JAAS:是 Java 授權與認證服務的縮寫,主要用於登錄認證與角色權限等管理的 API。
JCA 和 JCE 並不提供任何加密算法的實現,只是提供接口供第三方實現加密算法。第三方廠 商根據 JCE 的接口實現加密算法,並打包成 Provide(安全提供者),就可以動態地添加到 Java 之中。加載第三方的 JCE 實現,主要有兩種方式:a.使用 JRE 的 java.security 文件在 JVM 啟 動時添加;b.使用 Provider 管理器 java.security.Security 的靜態方法在運行時添加。hotspot虛擬機默認實現了一個Provide-SunJCE,除了Java默認提供的之外,比較著名的第三方實現還有Bouncy Castle 開源類庫。
6.密碼學相關API
java.security.MessageDigest:產生消息摘要對象的工廠類
例子
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] bytes = digest.digest("MD5".getBytes());
加密密鑰:
java.security.Key:所有密鑰的抽象表示,含有算法、二進制編碼、編碼格式
java.security.spec.KeySpec:密鑰規范(空接口),其下的實現類專用於將二進制密鑰數據規 范化為密鑰對象。
java.security.spec.EncodeedKeySpec:編碼的密鑰規范,主要是公鑰和私鑰規范的抽象。 公鑰采用 X.509 編碼,對應於 X509EncodedKeySpec 類;私鑰采用 PKCS#8 編碼,對應於 PKCS8EncodedKeySpec 類。
java.security.PublicKey:非對稱密碼公鑰的抽象接口(空接口)
java.security.PrivateKey:非對稱密碼私鑰的抽象接口(空接口)
java.security.KeyPair:非對稱密鑰的包裝類,稱為密鑰對接口,里面有 getPublicKey 和 getPrivateKey 兩個方法
java.security.KeyPairGenerator:隨機產生非對稱密鑰對的工廠
java.security.KeyFactory:將二進制數據根據密鑰規范還原非對稱密鑰的公鑰或者私鑰
java.security.SecureRandom:強隨機數發生器,可由第三方提供隨機算法
javax.crypto.KeyGenerator:隨機產生對稱密鑰的工廠
數字簽名:
java.security.Signature:產生數字簽名對象的工廠類
例子
public static void keyDemo(byte[] privateKey,byte[] publicKey,byte[] content) throws Exception{
KeyFactory keyf = KeyFactory.getInstance("RSA");
//私鑰
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
PrivateKey prikey = keyf.generatePrivate(keySpec);
//公鑰
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKey);
PublicKey pubKey = keyf.generatePublic(x509EncodedKeySpec);
//簽名
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(prikey);
signature.update(content);
byte[] sign = signature.sign();
//校驗簽名
signature.initVerify(pubKey);
signature.verify(sign);
}
加密解密:
javax.crypto.Cipher:JCE核心的引擎類,提供加密解密功能。
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
KeyPair pair = generator.generateKeyPair();
//私鑰
PrivateKey prikey = pair.getPrivate();
//公鑰
PublicKey pubKey = pair.getPublic();
//非對稱加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.PUBLIC_KEY,pubKey);
byte[] m = cipher.doFinal(content);
Cipher cipher1 = Cipher.getInstance("RSA");
//非對稱解密
cipher1.init(Cipher.PRIVATE_KEY,prikey);
cipher1.update(m);
byte[] s = cipher1.doFinal();
System.out.println(new String(s));
總結:Java密碼學相關的API提供了大量的工廠方法getInstance(String algorithm),根據不同的算法返回不同的實現類。這樣的好處顯而易見,這可以讓你的代碼與具體的算法無關,如果需要更換算法只需要把RSA換成其他算法,其他部分都不需要改變。甚至你還可以把String algorithm參數寫到配置文件中,到時候連代碼都不用改,直接改配置文件即可。