消息摘要算法
本文檔依賴的jar maven地址如下:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.57</version>
</dependency>
分類名詞解釋
- MD
message Digest 消息摘要 - SHA
Secure hash algorithm安全散列 - MAC
message authenttication code 消息認證碼
三個名詞的作用
驗證數據的完整性(比如maven倉庫的md5數據完整性比對)
消息摘要算法是數字簽名的核心算法
MD算法分類
- MD5
- MD家族(生成都是128位摘要信息 如果md2,md4)
MD算法特點
單項加密
不可逆
MD5的實現方

package com.ztgeo.secret;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Hex;
public class MDDemo {
//md家族的加解密算法
private static String reqStr= "MD5需要加密的數據";
public static void main(String[] args) {
secretMD5();
}
public static void secretMD5(){
try {
//使用原生jdk就可以進行md5的加密
MessageDigest md = MessageDigest.getInstance("MD5");
//進行消息摘要(md5加密)
byte[] md5Bytes =md.digest(reqStr.getBytes());
System.out.println("md5加密后未經轉換的byte[]后的結果:"+md5Bytes);
System.out.println("md5加密后轉換成string后的結果:"+new String(md5Bytes));
//轉換后的長度沒有128 只有11位 就算轉換成string也是如下亂碼:??????'??9?O??s4
//所以md5加密后的數據 不能直接使用 應該使用16進制轉換后的結果作為加密結果
//恰巧bc和cc中都有該功能的方法 一般選擇cc中方法
System.out.println("轉換成16進制之后的加密數組:"+Hex.encodeHexString(md5Bytes));
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
該算法 也同樣支持md2 只需要在獲得實例的時候傳入"MD2"即可
但是jdk沒有提供md4的實現 強制使用md4獲得實例會報錯
使用bc實現md4或者其他加密方式
private static void BCMD4(){
//使用bc包實現md4的算法 加密
Digest digest = new MD4Digest();
//預處理 md4需要加密的字符串(類似讀取 輸入流)
digest.update(reqStr.getBytes(), 0,reqStr.getBytes().length);
//使用byte數組去接收結果 相當于處理完了 用容器去承載結果
byte[] md4Byte = new byte[digest.getDigestSize()];
///讀出到輸入流
digest.doFinal(md4Byte, 0);
//這個時候結果容器被裝滿 使用bc自帶的64位轉碼進行轉碼
System.out.println("BC加密后的MD4加密結果:"+org.bouncycastle.util.encoders.Hex.toHexString(md4Byte));
}
當然 也可以用cc去實現相同的功能 只是在cc中并沒有提供md4的實現,猜測cc只是簡化輔助jdk的md功能 沒有做功能的延伸
//使用cc實現md的加密
//如果看源碼會發現 實際上cc并沒有去自己寫md的實現 只是引用來了jdk的md相應實現
public static void ccMD5(){
//這里需要提的而是 cc實現 md5的方法中 有個方法簡化了hex轉化64位的操作
System.out.println("CCmd5的簡單實現:"+DigestUtils.md5Hex(reqStr.getBytes()));
}
md算法的總結
- 使用jdk的方法是偏底層的,不提供16進制轉換
- bc的優勢在于提供了md4的實現(jdk和cc沒有)
- cc實現了hex進制轉換的直接使用 但只是簡化了jdk的方法 沒有自己實現
md加密方式的應用
注冊時用戶名明文 密碼變為不可逆 密文 存入數據庫
登錄時用戶名明文 密碼直接拿去數據庫比對
這樣有效的防止了信息泄露(就算拿到數據庫還是不知道密碼)
SHA
- 安全散列算法
- 固定長度的摘要信息
- 很多場景下 被稱為md5的繼承者
- 美國國家安全局設計的(背景強大)
- 由MD4演變而來
- 內容稍有不同結果就大相徑庭 很難被破譯
SHA的分類
- SHA-1
- SHA-2
- SHA-224
- SHA-256
- SHA-384
- SHA-512
算法的實現

依然沒有cc的算法.是因為cc又是對jdk的簡化操作
SHA的算法應用
防止數據傳輸過程中被篡改,保證數據的完整性
常用的傳輸方式是在url上傳參 并發送sha的消息摘要,,對方進行消息摘要的對比 看傳輸數據是否發生了篡改
MAC
- 兼容了md和sha的特性
- 加入了秘鑰(hmac 含有秘鑰的sha算法)
MAC的分類
-
MD系列
- HmacMD2
- HmacMD4
- HmacMD5
-
SHA系列
- HmacSHA1
- HmacSHA2
- HmacSHA224
- HmacSHA256
- HmacSHA384
- HmacSHA512
MAC算法的摘要長度和實現方

MAC的代碼實現
package com.ztgeo.secret;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.DecoderException;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;
public class MacDemo {
//mac安全散列算法的實現(有秘鑰)
private static String reqStr="需要被mac摘要的數據";
public static void main(String[] args) {
jdkHmacMD5();
bHmacMD5();
}
public static void jdkHmacMD5(){
try {
//獲得秘鑰工廠
KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
//一下兩步是是隨機生產key 但實際情況 需要制定key
/*//生成秘鑰
SecretKey key = keyGenerator.generateKey();
//獲得秘鑰
byte[] keyByte = key.getEncoded();*/
byte[] keyByte = org.apache.commons.codec.binary.Hex.decodeHex(new char[]{'a','a','a','a','a','a','a','a','a','a'});
//還原秘鑰 數組秘鑰 通過類進行還原
SecretKey restoreKey = new SecretKeySpec(keyByte, "HmacMD5");
//實例化MAC 使用秘鑰還原
Mac mac = Mac.getInstance(restoreKey.getAlgorithm());
//初始化mac
mac.init(restoreKey);
//執行加密(摘要)
byte[] HmacMd5Bytes = mac.doFinal(reqStr.getBytes());
//輸出摘要的結果
System.out.println("jkd hmacMD5結果:"+Hex.toHexString(HmacMd5Bytes));
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DecoderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//bc實現mac md5算法
public static void bHmacMD5(){
//實例化mac
HMac hmac = new HMac(new MD5Digest());
//初始化mac
hmac.init(new KeyParameter(Hex.decode("aaaaaaaaaa")));
//讀入流
hmac.update(reqStr.getBytes(),0,reqStr.getBytes().length);
//準備容器
byte[] hmacMD5Bytes = new byte[hmac.getMacSize()];
//放置輸出結果
hmac.doFinal(hmacMD5Bytes, 0);
//輸出結果
System.out.println("bcHmacMD5結果:"+Hex.toHexString(hmacMD5Bytes));
}
}
對稱加密算法
加密秘鑰和解密秘鑰相同
對稱加密算法的特點
- 初等的加密算法(安全級別不高)
- DES(代表性的加密算法,長度不夠 安全性低 已被破解)
- 3DES
- AES(替代DES)
- PBE
- IDEA
DES詳解
出身
ibm提交美國,98年后被破解,目前不具備安全性
實現方式和實現方

使用jdk實現DES算法的加解密
package com.ztgeo.secret;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import org.apache.commons.codec.binary.Hex;
public class DESDemo {
private static String reqStr ="需要被加密內容!!";
public static void main(String[] args) {
jdkDES();
}
public static void jdkDES(){
try {
//生成秘鑰材料
/*KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
//指定秘鑰長度 DES是56位
keyGenerator.init(56);
SecretKey key = keyGenerator.generateKey();
//獲得程序產生的key
byte[] keyByte = key.getEncoded();*/
//當然 可以自己指byte數組類型的秘鑰
byte[] keyByte = "15062101243".getBytes(); //秘鑰
//秘鑰材料轉換
DESKeySpec desKeySpec = new DESKeySpec(keyByte);
//生成真正的key
//實例化秘鑰工廠(指定加密方式)
SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
Key convertSecretKey = factory.generateSecret(desKeySpec);
//加密 (需要填充加解密的算法/工作方式/填充方式)
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
//加密模式ENCRYPT_MODE 和轉換可以使用的key
cipher.init(cipher.ENCRYPT_MODE, convertSecretKey);
//執行加密操作
byte[] result = cipher.doFinal(reqStr.getBytes());
System.out.println("使用JDK加密DES:"+Hex.encodeHexString(result));
//解密操作
//依然使用cipher進行解密 需要的秘鑰 也需要秘鑰轉換
cipher.init(cipher.DECRYPT_MODE, convertSecretKey);
//執行加密操作 結果轉成string
result = cipher.doFinal(result);
System.out.println("使用JDK解密DES:"+new String(result));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//bc的DES實現 可以通過secret添加provide進行實現 實現方式和jdk類似 這里不做贅述
}
3DES(三重DES)
三重DES的必要性
- DES違反了柯克霍夫原則(算法半公開) 所以安全性不高
- DES的背景是美國安全局,所以是否有后門 不敢確保
三重DES的好處
- 密碼長度增強
- 迭代次數增多
長度和實現方

JDK的實現
package com.ztgeo.secret;
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import org.apache.commons.codec.binary.Hex;
public class DES3 {
private static String reqStr ="需要被加密內容!!";
public static void main(String[] args) {
jdk3des();
}
public static void jdk3des(){
//jdk的三重des和des實現都是類似的 我們直接copy代碼
try {
//生成秘鑰材料
KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");
//指定秘鑰長度 3DES是168位
//keyGenerator.init(168);
//當然 如果不想記什么算法多少位 可以使用根據getInstance對字符串變能量獲得默認長度的秘鑰
keyGenerator.init(new SecureRandom());
SecretKey key = keyGenerator.generateKey();
//獲得程序產生的key
byte[] keyByte = key.getEncoded();
//當然 可以自己指byte數組類型的秘鑰 但目前報錯 原因未知
//byte[] keyByte = "15062101243".getBytes(); //秘鑰
//秘鑰材料轉換
DESedeKeySpec desKeySpec = new DESedeKeySpec(keyByte);
//生成真正的key
//實例化秘鑰工廠(指定加密方式)
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
Key convertSecretKey = factory.generateSecret(desKeySpec);
//加密 (需要填充加解密的算法/工作方式/填充方式)
Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
//加密模式ENCRYPT_MODE 和轉換可以使用的key
cipher.init(cipher.ENCRYPT_MODE, convertSecretKey);
//執行加密操作
byte[] result = cipher.doFinal(reqStr.getBytes());
System.out.println("使用JDK加密3DES:"+Hex.encodeHexString(result));
//解密操作
//依然使用cipher進行解密 需要的秘鑰 也需要秘鑰轉換
cipher.init(cipher.DECRYPT_MODE, convertSecretKey);
//執行加密操作 結果轉成string
result = cipher.doFinal(result);
System.out.println("使用JDK解密3DES:"+new String(result));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
AES
AES的產生原因
- DES安全性不要
- 3DES效率不高
- AES是DES(包括3DES的替代品)
- 對稱加密的首選就是AES 使用率最高
- AES目前官方并沒有確認被破解
AES的應用范圍
AES用于移動通訊系統加密以及基于SSH協議的軟件
算法實現

jdk的實現(bc的實現和aes十分類似 不舉例了)
package com.ztgeo.secret;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class AESDemo {
private static String reqStr ="需要被加密內容!!";
public static void main(String[] args) {
jdkAes();
}
public static void jdkAes(){
try {
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey sekey = keyGenerator.generateKey();
//獲得程序產生的key
byte[] keyByte = sekey.getEncoded();
//轉換key
Key key = new SecretKeySpec(keyByte, "AES");
//加密 填充
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] resultByte = cipher.doFinal(reqStr.getBytes());
System.out.println("AES加密后的內容(base64之后):"+Base64.encodeBase64String(resultByte));
//解密
cipher.init(Cipher.DECRYPT_MODE, key);
resultByte = cipher.doFinal(resultByte);
System.out.println("使用JDK解密AES操作:"+new String(resultByte));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
對稱加密算法之----PBE
- pbe算法結合了消息摘要算法和對稱加密算法的所有優點
- pbe(password based encryption)基于口令的加密
- 只是對已有算法的包裝
- JDK,BC
- 鹽(秘鑰口令和擾碼)
- 是一種綜合性算法(消息摘要+對稱加密) 常見 PBEWithMD5AndDES
PBE算法的實現


演示jdk實現PBE的算法
package com.ztgeo.secret;
import java.security.Key;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import org.apache.commons.codec.binary.Base64;
public class PBEDemo {
private static String reqStr = "需要被加密的內容";
public static void main(String[] args) {
jdkPBE();
}
public static void jdkPBE(){
try {
//初始化鹽 鹽可以理解為隨機數
SecureRandom random = new SecureRandom();
//用8位 產生鹽
byte[] salt = random.generateSeed(8);
//口令轉秘鑰
String password = "12345687";
//密碼轉換成口令秘鑰
PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBEWITHMD5andDES");
Key key = factory.generateSecret(pbeKeySpec);
//加密
//將鹽構成params
PBEParameterSpec parameterSpec = new PBEParameterSpec(salt, 100);
Cipher cipher = Cipher.getInstance("PBEWITHMD5andDES");
cipher.init(Cipher.ENCRYPT_MODE, key,parameterSpec);
byte[] byteResult = cipher.doFinal(reqStr.getBytes());
System.out.println("jdk使用PBE加密后的結果:"+ Base64.encodeBase64String(byteResult));
//解密
cipher.init(Cipher.DECRYPT_MODE,key,parameterSpec);//秘鑰 鹽
byteResult = cipher.doFinal(byteResult);
System.out.println("jdk使用PBE解密后的結果:"+ new String(byteResult));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
PBE在的實際使用

由圖中可以看出,解謎.不僅要知道解密的秘鑰,還要知道加密時實時產生的隨機數才能正確解密,極大提高了數據性;
非對稱加密算法
因為對稱加密算法是雙方秘鑰相同.所以又叫做初等加密算法
非對稱加密算法的特點
- 高級加密算法(秘鑰不對稱)
- 雙保險(類似vip銀行客戶保險柜原理.銀行一把鑰匙.客戶一把鑰匙)
- 公鑰,私鑰 (都是成對出現的)
非對稱加密的分類
- DH(Diffie-Hellman)密鑰交換算法
- RSA-基于因子分解(三個人姓氏開頭,應用最廣)
- ElGamal-基于離散對數
- ECC(橢圓曲線加密)
DH加密算法
- 非對稱加密的鼻祖
- 是為了解決對稱加密算法密鑰的傳輸安全級別低的問題應運而生的
- 構建本地秘鑰 解決秘鑰傳遞的問題
DH相關實現方

JDK實現加密算法使用類
加密方:
- KeyPairGenerator 秘鑰對的 生產類
- KeyPair 秘鑰對 可以產生公鑰和私鑰
- PublicKey 公鑰
解密方:
- KeyFactory 秘鑰工廠(根據規范生成公鑰私鑰) 還原秘鑰
- X509EncodeKeySpec 根據ASN.1進行秘鑰編碼
- DHPublicKey
- DHParameterSpec DH算法中 參數的集合類
- KeyPairGenerator
- PrivateKey
秘鑰構建
KeyAgreement 提供秘鑰協議的類
SecretKey 秘密秘鑰 生成分組的秘密秘鑰
加密,解密
Cipher 加密解密 提供密碼功能類
DH加密的步驟
- 發送方發送公鑰載體
- 接收方根據發送方公鑰產生接收方公鑰載體
- 根據接受方公鑰載體產生本地秘鑰
- 發送接收方公鑰載體
- 接收方根據接收方的公鑰載體 產生本地秘鑰
- 對比雙方本地秘鑰 完全相同后發送方根據本地秘鑰加密數據
- 接收方 根據本地秘鑰進行 解密數據
在此過程中,雙方的本地秘鑰不同,但兩次發送,彼此依賴生成,形成完美的閉環,具體代碼如下:
package com.ztgeo.secret;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import org.apache.commons.codec.binary.Base64;
//非對稱加密
public class DHDemo {
private static String reqStr = "需要被加密的數據123456";
public static void main(String[] args) {
try {
//1.初始化發送方的秘鑰
//鑰匙對工廠產生鑰匙對
KeyPairGenerator sendKeyPairGenerator = KeyPairGenerator.getInstance("DH");
sendKeyPairGenerator.initialize(512);
//鑰匙對 用來存放公鑰和私鑰
KeyPair sendKeyPair =sendKeyPairGenerator.generateKeyPair();
//獲得公鑰載體 發送給接收方 (網絡,文件...)
byte[] sendPublicKeyEnc = sendKeyPair.getPublic().getEncoded();
//2.初始化接收方秘鑰 推算出 公鑰
KeyFactory reciverKeyFactory = KeyFactory.getInstance("DH");
//秘鑰標準
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(sendPublicKeyEnc);
//通過標準和 公鑰載體 獲得公鑰
PublicKey reciverPublicKey = reciverKeyFactory.generatePublic(x509EncodedKeySpec);
//獲得公鑰參數 用來構建鑰匙對
DHParameterSpec dhParameterSpec = ((DHPublicKey)reciverPublicKey).getParams();
//從發送方載體中獲得了公鑰參數 可以構建 參數對了
KeyPairGenerator receiverKeyPairGenerator = KeyPairGenerator.getInstance("DH");
receiverKeyPairGenerator.initialize(dhParameterSpec);
KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair();
//接收方 公鑰載體
byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded();
//3.秘鑰構建(私鑰) 具體可分為 發送方的私鑰構建 和接收方的 私鑰構建
//接受方
KeyAgreement receviverKeyAgreement = KeyAgreement.getInstance("DH");
//使用私鑰進行初始化
receviverKeyAgreement.init(receiverKeyPair.getPrivate());
receviverKeyAgreement.doPhase(reciverPublicKey, true);
//本地私鑰產生 并發送
SecretKey receiverDesKey = receviverKeyAgreement.generateSecret("DES");
//發送方(根據接收方 第一次返回的公鑰載體進行生成私鑰 并反推成本地秘鑰)
KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);
PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
senderKeyAgreement.init(sendKeyPair.getPrivate());
senderKeyAgreement.doPhase(senderPublicKey, true);
SecretKey senderDesKey = senderKeyAgreement.generateSecret("DES");
//接收方 根據發送方私鑰產生了 本地秘鑰
//發送方 也根據接收方傳過來的 公鑰 產生了本地秘鑰
//驗證 雙方本地秘鑰是否相同
if(Objects.equals(receiverDesKey, senderDesKey)){
System.out.println("驗證成功,雙方產生的本地秘鑰相同!!");
}
//4.加密數據
//發送方根據 本地 私鑰 加密數據
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
byte[] result = cipher.doFinal(reqStr.getBytes());
System.out.println("使用DH加密的數據是:"+Base64.encodeBase64String(result));
//5.客戶端解密數據
//接收方根據 本地秘鑰進行解密
cipher.init(Cipher.DECRYPT_MODE, receiverDesKey);
result = cipher.doFinal(result);
System.out.println("使用DH解密后的數據是:"+new String(result));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
具體實現的流程圖如下:

流程模板分析
1、甲方(消息發送方,下同)構建密鑰對(公鑰+私鑰),甲方公布公鑰給乙方(消息接收方,下同)
2、乙方以甲方發送過來的公鑰作為參數構造密鑰對(公鑰+私鑰),將構造出來的公鑰公布給甲方
3、甲方用“甲方的私鑰+乙方的公鑰”構造本地密鑰
4、乙方用“乙方的私鑰+甲方的公鑰”構造本地的密鑰
5、這個時候,甲乙兩方本地新構造出來的密鑰應該一樣。然后就可以使用AES這類對稱加密算法結合密鑰進行數據的安全傳送了。傳送過程參考AES的相關算法
DH加密算法較為復雜,進一步學習可以參考這篇博客
http://blog.csdn.net/kongqz/article/details/6302913
非對稱加密算法-RSA
- 唯一廣泛接受并實現
- 可用于數據加密&數字簽名
- 公鑰加密,私鑰解密
- 私鑰加密,公鑰解密
RSA長度和填充及是實現方式

具體實現:
package com.ztgeo.secret;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
import com.sun.org.apache.xml.internal.security.encryption.CipherData;
public class RSADemo {
private static String reqStr = "需要被加解密的字符串!!12345689";
public static void main(String[] args) {
jdkRSA();
}
public static void jdkRSA(){
try {
//1.初始化秘鑰
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
//公鑰 私鑰
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic();
RSAPrivateKey rasPrivateKey = (RSAPrivateKey)keyPair.getPrivate();
System.out.println("公鑰:"+Base64.encodeBase64String(rsaPublicKey.getEncoded()));
System.out.println("私鑰:"+Base64.encodeBase64String(rasPrivateKey.getEncoded()));
//2.使用私鑰加密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rasPrivateKey.getEncoded());
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);//私鑰加密
byte[] result = cipher.doFinal(reqStr.getBytes());
System.out.println("RSA私鑰加密后的結果:"+Base64.encodeBase64String(result));
//3.發送發 發送公鑰 接收方使用公鑰解密 密文
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded());
keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
result = cipher.doFinal(result);
System.out.println("公鑰解密的結果是:"+new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
}