1、加密概述:
加密就是是以某種特殊的演算法改變原有的資訊資料,使得未授權的使用者即使以獲得了加密的資訊,但因不知解密方式,仍無法瞭解資訊的內容。大體上又分為雙向加密和單向加密。
2、單項加密
2.1、概述:
單向加密又稱為不可逆加密演算法,在加密過程中不使用金鑰,明文由系統加密成密文,密文無法破解,一般都是採用驗證的方式,具體是:在驗證過程中,重新輸入明文,並經過同樣的加密演算法後,得到相同的密文。單向加密廣泛用於口令加密。
2.2、特點:
(1)對同一訊息反覆執行加密得到相同的密文;
(2)加密演算法生成密文不可預見;
(3)不可逆,一般不能通過密文獲取明文
2.3、類別
2.3.1、MD5加密
2.3.1.1、概述:
MD5的全稱是Message-Digest Algorithm 5(資訊-摘要演算法),在90年代初由MIT Laboratory for Computer Science和RSA Data Security Inc的Ronald L. Rivest開發出來,經MD2、MD3和MD4發展而來。
MD5用於確保資訊傳輸完整一致。是計算機廣泛使用的雜湊演算法之一(又譯摘要演算法、雜湊演算法),主流程式語言普遍已有MD5實現。將資料(如漢字)運算為另一固定長度值,是雜湊演算法的基礎原理,MD5的前身有MD2、MD3和MD4。
MD5的作用是讓大容量資訊在用數字簽名軟體簽署私人金鑰前被"壓縮"成一種保密的格式(就是把一個任意長度的位元組串變換成一定長的十六進位制數字串)。
2.3.1.2、演算法原理:
對MD5演算法簡要的敘述可以為:MD5以512位分組來處理輸入的資訊,且每一分組又被劃分為16個32位子分組,經過了一系列的處理後,演算法的輸出由四個32位分組組成,將這四個32位分組級聯後將生成一個128位雜湊值。
在MD5演算法中,首先需要對資訊進行填充,使其位長對512求餘的結果等於448。因此,資訊的位長(Bits Length)將被擴充套件至N*512+448,N為一個非負整數,N可以是零。填充的方法如下,在資訊的後面填充一個1和無數個0,直到滿足上面的條件時才停止用0對資訊的填充。然後,在這個結果後面附加一個以64位二進位制表示的填充前資訊長度。經過這兩步的處理,資訊的位長=N*512+448+64=(N+1)*512,即長度恰好是512的整數倍。這樣做的原因是為滿足後面處理中對資訊長度的要求。
2.3.1.3、java程式碼中使用MD5加密
/**
* md5計算.
*
* @param datas
* 待計算的資料
* @return 計算結果
*/
public static byte[] md5(byte[] datas) {
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
md.reset();
md.update(datas);
return md.digest();
} catch (Exception e) {
log.error("MD5計算失敗", e);
return null;
}
}
2.3.2、SHA加密
2.3.2.1、概述
其思想是接收一段明文,然後以一種不可逆的方式將它轉換成一段(通常更小)的密文。可以簡單的理解為取一串輸入碼(稱為預對映或資訊),並把他們轉化為長度較短、位數固定的輸出序列的過程。
安全雜湊演算法SHA(Secure Hash Algorithm,SHA)是美國國家標準技術研究所釋出的國家標準FIPS PUB 180,最新的標準已經於2008年更新到FIPS PUB 180-3。其中規定了SHA-1,SHA-224,SHA-256,SHA-384,和SHA-512這幾種單向雜湊演算法。SHA-1,SHA-224和SHA-256適用於長度不超過2^64二進位制位的訊息。SHA-384和SHA-512適用於長度不超過2^128二進位制位的訊息。
2.3.2.2、原理
SHA-1是一種資料加密演算法,該演算法的思想是接收一段明文,然後以一種不可逆的方式將它轉換成一段(通常更小)密文,也可以簡單的理解為取一串輸入碼(稱為預對映或資訊),並把它們轉化為長度較短、位數固定的輸出序列即雜湊值(也稱為資訊摘要或資訊認證程式碼)的過程。
單向雜湊函式的安全性在於其產生雜湊值的操作過程具有較強的單向性。如果在輸入序列中嵌入密碼,那麼任何人在不知道密碼的情況下都不能產生正確的雜湊值,從而保證了其安全性。SHA將輸入流按照每塊512位(64個位元組)進行分塊,併產生20個位元組的被稱為資訊認證程式碼或資訊摘要的輸出。
該演算法輸入報文的長度不限,產生的輸出是一個160位的報文摘要。輸入是按512 位的分組進行處理的。SHA-1是不可逆的、防衝突,並具有良好的雪崩效應。
通過雜湊演算法可實現數字簽名實現,數字簽名的原理是將要傳送的明文通過一種函式運算(Hash)轉換成報文摘要(不同的明文對應不同的報文摘要),報文摘要加密後與明文一起傳送給接受方,接受方將接受的明文產生新的報文摘要與傳送方的發來報文摘要解密比較,比較結果一致表示明文未被改動,如果不一致表示明文已被篡改。
MAC (資訊認證程式碼)就是一個雜湊結果,其中部分輸入資訊是密碼,只有知道這個密碼的參與者才能再次計算和驗證MAC碼的合法性。
2.3.2.3、java中的SHA實現
/**
* SHA1簽名
* @param paramStr 要加簽的字串
* @return
*/
public static String SHA1(String paramStr) {
MessageDigest alg;
String result = "";
String tmp = "";
try {
alg = MessageDigest.getInstance("SHA-1");
alg.update(paramStr.getBytes());
byte[] bts = alg.digest(); for (int i = 0; i < bts.length; i++) {
tmp = (Integer.toHexString(bts[i] & 0xFF));
if (tmp.length() == 1)
result += "0";
result += tmp;
}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} return result;
}
2.4、SHA與MD5的區別:
(1)對強行攻擊的安全性:最顯著和最重要的區別是:SHA-1的摘要比MD5的摘要長32位。使用強行技術,產生任何一個報文使其摘要等於給定摘要的難度對MD5是是2^128數量級的操作,而對SHA-1則是2^160數量級的操作。這樣,SHA-1對強行攻擊有更大的強度。
(2)對密碼分析的安全性:由於MD5的設計,易受密碼分析的攻擊,SHA-1不易受這樣的攻擊。
3、雙向加密
3.1概述
大體意思是明文加密後形成密文,可以通過演算法還原成明文。
3.2分類
3.2.1對稱加密
3.2.1.1概述
對稱加密演算法是應用較早的加密演算法,技術成熟。在對稱加密演算法中,資料發信方將明文(原始資料)和加密金鑰(mi yue)一起經過特殊加密演算法處理後,使其變成複雜的加密密文傳送出去。收信方收到密文後,若想解讀原文,則需要使用加密用過的金鑰及相同演算法的逆演算法對密文進行解密,才能使其恢復成可讀明文。在對稱加密演算法中,使用的金鑰只有一個,發收信雙方都使用這個金鑰對資料進行加密和解密,這就要求解密方事先必須知道加密金鑰。
3.2.1.2特點
優點:
(1)演算法公開,計算量小、加密速度快、加密效率高
缺點:
(1)交易雙方都使用同樣的金鑰,安全性得不到保證
(2)每對使用者每次使用對稱加密演算法時,都需要使用其他人不知道的唯一金鑰,這會使得發收信雙方所擁有的鑰匙數量呈幾何級數增長,金鑰管理成為使用者的負擔。對稱加密演算法在分散式網路系統上使用較為困難,主要是因為金鑰管理困難,使用成本較高。
3.2.1.3常用對稱加密演算法
基於“對稱金鑰”的加密演算法比較常用的主要有:DES 、 3DES 、AES
(1)DES
概述:
DES演算法全稱為Data Encryption Standard,即資料加密演算法,它是IBM公司於1975年研究成功並公開發表的。DES演算法的入口引數有三個:Key、Data、Mode。其中Key為8個位元組共64位,是DES演算法的工作金鑰;Data也為8個位元組64位,是要被加密或被解密的資料;Mode為DES的工作方式,有兩種:加密或解密。
演算法原理:
DES演算法的入口引數有三個:Key、Data、Mode。
(1)Key為8個位元組共64位,是DES演算法的工作金鑰;
(2)Data也為8個位元組64位,是要被加密或被解密的資料;
(3)Mode為DES的工作方式,有兩種:加密或解密。
連結:https://www.zhihu.com/question/36767829/answer/68911532
演算法應用:
java程式碼實現:
/**
* 3DES加密
*
* @param key
* 金鑰資訊
* @param content
* 待加密資訊
* @return
* @throws Exception
*/
public static byte[] encode3DES(byte[] key, byte[] content) throws Exception {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// 不是8的倍數的,補足
if (key.length % 8 != 0) {
int groups = key.length / 8 + (key.length % 8 != 0 ? 1 : 0);
byte[] temp = new byte[groups * 8];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
}
// 長度為16位,轉換成24位的金鑰
if (key.length == 16) {
byte[] temp = new byte[24];
System.arraycopy(key, 0, temp, 0, key.length);
System.arraycopy(key, 0, temp, key.length, temp.length - key.length);
key = temp;
} // 不是8的倍數的,補足
byte[] srcBytes = content;
if (srcBytes.length % 8 != 0) {
int groups = content.length / 8 + (content.length % 8 != 0 ? 1 : 0);
srcBytes = new byte[groups * 8];
Arrays.fill(srcBytes, (byte) 0);
System.arraycopy(content, 0, srcBytes, 0, content.length);
} SecretKey deskey = new SecretKeySpec(key, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, deskey);
byte[] temp = cipher.doFinal(srcBytes);
byte[] tgtBytes = new byte[content.length];
System.arraycopy(temp, 0, tgtBytes, 0, tgtBytes.length);
return tgtBytes;
} /**
* 3DES解密
*
* @param key
* 金鑰
* @param content
* 待解密資訊
* @return
* @throws Exception
*/
public static byte[] decode3DES(byte[] key, byte[] content) throws Exception {
// 不是8的倍數的,補足
if (key.length % 8 != 0) {
int groups = key.length / 8 + (key.length % 8 != 0 ? 1 : 0);
byte[] temp = new byte[groups * 8];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
}
// 長度為16位,轉換成24位的金鑰
if (key.length == 16) {
byte[] temp = new byte[24];
System.arraycopy(key, 0, temp, 0, key.length);
System.arraycopy(key, 0, temp, key.length, temp.length - key.length);
key = temp;
} // 不是8的倍數的,補足
byte[] srcBytes = content;
if (srcBytes.length % 8 != 0) {
int groups = content.length / 8 + (content.length % 8 != 0 ? 1 : 0);
srcBytes = new byte[groups * 8];
Arrays.fill(srcBytes, (byte) 0);
System.arraycopy(content, 0, srcBytes, 0, content.length);
} SecretKey deskey = new SecretKeySpec(key, "DESede");
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, deskey);
byte[] tgtBytes = cipher.doFinal(srcBytes);
return tgtBytes;
} /**
* DES加密
*
* @param key
* 金鑰資訊
* @param content
* 待加密資訊
* @return
* @throws Exception
*/
public static byte[] encodeDES(byte[] key, byte[] content) throws Exception {
// 不是8的倍數的,補足
if (key.length % 8 != 0) {
int groups = key.length / 8 + (key.length % 8 != 0 ? 1 : 0);
byte[] temp = new byte[groups * 8];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
} // 不是8的倍數的,補足
byte[] srcBytes = content;
if (srcBytes.length % 8 != 0) {
int groups = content.length / 8 + (content.length % 8 != 0 ? 1 : 0);
srcBytes = new byte[groups * 8];
Arrays.fill(srcBytes, (byte) 0);
System.arraycopy(content, 0, srcBytes, 0, content.length);
} IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv, sr);
byte[] tgtBytes = cipher.doFinal(srcBytes);
return tgtBytes;
} /**
* DES解密
*
* @param key
* 金鑰資訊
* @param content
* 待加密資訊
* @return
* @throws Exception
*/
public static byte[] decodeDES(byte[] key, byte[] content) throws Exception {
// 不是8的倍數的,補足
if (key.length % 8 != 0) {
int groups = key.length / 8 + (key.length % 8 != 0 ? 1 : 0);
byte[] temp = new byte[groups * 8];
Arrays.fill(temp, (byte) 0);
System.arraycopy(key, 0, temp, 0, key.length);
key = temp;
}
// 不是8的倍數的,補足
byte[] srcBytes = content;
if (srcBytes.length % 8 != 0) {
int groups = content.length / 8 + (content.length % 8 != 0 ? 1 : 0);
srcBytes = new byte[groups * 8];
Arrays.fill(srcBytes, (byte) 0);
System.arraycopy(content, 0, srcBytes, 0, content.length);
} IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, iv, sr);
byte[] tgtBytes = cipher.doFinal(content);
return tgtBytes;
}
(2)3DES
概述:
3DES(或稱為Triple DES)是三重資料加密演算法(TDEA,Triple Data Encryption Algorithm)塊密碼的通稱。它相當於是對每個資料塊應用三次DES加密演算法。由於計算機運算能力的增強,原版DES密碼的金鑰長度變得容易被暴力破解;3DES即是設計用來提供一種相對簡單的方法,即通過增加DES的金鑰長度來避免類似的攻擊,而不是設計一種全新的塊密碼演算法。
演算法原理:
package cn.mars.app.txn.bjyl; import java.security.Key;
import java.security.Security; import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec; /**
* 3DES加密
*
* @version 1.0
* @author
*
*/
public class DesUtil { /**
* 金鑰演算法
*/
public static final String KEY_ALGORITHM = "DESede";
public static final String CIPHER_ALGORITHM = "DESede/ECB/PKCS5Padding";
private static String strDefaultKey = "national";
private Cipher encryptCipher = null;
private Cipher decryptCipher = null; public DesUtil() throws Exception {
this(strDefaultKey);
} public static String byteArr2HexStr(byte[] arrB) throws Exception {
int iLen = arrB.length;
StringBuffer sb = new StringBuffer(iLen * 2);
for (int i = 0; i < iLen; i++) {
int intTmp = arrB[i];
while (intTmp < 0) {
intTmp = intTmp + 256;
}
if (intTmp < 16) {
sb.append("0");
}
sb.append(Integer.toString(intTmp, 16));
}
return sb.toString();
} public static byte[] hexStr2ByteArr(String strIn) throws Exception {
byte[] arrB = strIn.getBytes();
int iLen = arrB.length;
byte[] arrOut = new byte[iLen / 2];
for (int i = 0; i < iLen; i = i + 2) {
String strTmp = new String(arrB, i, 2);
arrOut[i / 2] = (byte) Integer.parseInt(strTmp, 16);
}
return arrOut;
}
/**
* @param strKey
* @throws Exception
*/
public DesUtil(String strKey) throws Exception {
Security.addProvider(new com.sun.crypto.provider.SunJCE());
Key key = getKey(StringUtil.hexStringToByteArray(strKey));
encryptCipher = Cipher.getInstance("DES/ECB/NoPadding");
encryptCipher.init(Cipher.ENCRYPT_MODE, key);
decryptCipher = Cipher.getInstance("DES/ECB/NoPadding");
decryptCipher.init(Cipher.DECRYPT_MODE, key);
} public byte[] encrypt(byte[] arrB) throws Exception {
return encryptCipher.doFinal(arrB);
} public String encrypt(String strIn) throws Exception {
return byteArr2HexStr(encrypt(strIn.getBytes()));
} public byte[] decrypt(byte[] arrB) throws Exception {
return decryptCipher.doFinal(arrB);
} public String decrypt(String strIn) throws Exception {
return new String(decrypt(hexStr2ByteArr(strIn)));
} private Key getKey(byte[] arrBTmp) throws Exception {
byte[] arrB = new byte[8];
for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
arrB[i] = arrBTmp[i];
}
Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");
return key;
} public static String printbytes(String tip, byte[] b) {
String ret = "";
String str;
System.out.println(tip);
for (int i = 0; i < b.length; i++) {
str = Integer.toHexString((int) (b[i] & 0xff));
if (str.length() == 1)
str = "0" + str;
System.out.print(str + " ");
ret = ret + str + " ";
}
return ret;
}
/**
* 加密
* @param data
* @param key
* @return
* @throws Exception
* @author yangxing
* 2014-7-22
*/
public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
Key k = toKey(key);// 還原金鑰
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, k);
return cipher.doFinal(data);
}
/**
* 解密
*
* @param data 待解密資料
* @param key 金鑰
* @return byte[] 解密資料
*/
public static byte[] decrypt(byte[] data, byte[] key) throws Exception {
// 還原金鑰
Key k = toKey(key);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
// 初始化,設定為解密模式
cipher.init(Cipher.DECRYPT_MODE, k);
// 執行操作
return cipher.doFinal(data);
}
/**
* 轉換金鑰
* @param key 二進位制金鑰
* @return key 金鑰
*/
public static Key toKey(byte[] key) throws Exception {
DESedeKeySpec dks = new DESedeKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
return keyFactory.generateSecret(dks);
} public static void main(String[] args) {
try {
byte[] data = { 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30 };
DesUtil des1 = new DesUtil("498F456AC9D9CBA0");
printbytes("data", des1.encrypt(data));
} catch (Exception e) {
e.printStackTrace();
}
}
}
(3)AES

java程式碼實現:
package cn.mars.app.txn.wanglian; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security; import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.jce.provider.BouncyCastleProvider; import cfca.util.Base64; /**
* java實現AES256加密解密
* @author xiaoqiang
*
*/ public class AES256Util { public static byte[] encrypt(String content, String password) {
try {
// "AES":請求的金鑰演算法的標準名稱
KeyGenerator kgen = KeyGenerator.getInstance("AES");
// 256:金鑰生成引數;securerandom:金鑰生成器的隨機源
SecureRandom securerandom = new SecureRandom(tohash256Deal(password));
kgen.init(256, securerandom);
// 生成祕密(對稱)金鑰
SecretKey secretKey = kgen.generateKey();
// 返回基本編碼格式的金鑰
byte[] enCodeFormat = secretKey.getEncoded();
// 根據給定的位元組陣列構造一個金鑰。enCodeFormat:金鑰內容;"AES":與給定的金鑰內容相關聯的金鑰演算法的名稱
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
// 將提供程式新增到下一個可用位置
Security.addProvider(new BouncyCastleProvider());
// 建立一個實現指定轉換的 Cipher物件,該轉換由指定的提供程式提供。
// "AES/ECB/PKCS7Padding":轉換的名稱;"BC":提供程式的名稱
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC"); cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteContent = content.getBytes("utf-8");
byte[] cryptograph = cipher.doFinal(byteContent);
byte[] encode = Base64.encode(cryptograph); return encode;
} catch (Exception e) {
e.printStackTrace();
}
return null;
} public static String decrypt(byte[] cryptograph, String password) {
try {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom securerandom = new SecureRandom(tohash256Deal(password));
kgen.init(256, securerandom);
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); cipher.init(Cipher.DECRYPT_MODE, key);
byte[] content = cipher.doFinal(Base64.decode(cryptograph));
return new String(content);
} catch (Exception e) {
e.printStackTrace();
}
return null;
} public static String parseByte2HexStr(byte buf[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < buf.length; i++) {
String hex = Integer.toHexString(buf[i] & 0xFF);
if (hex.length() == 1) {
hex = '0' + hex;
}
sb.append(hex.toUpperCase());
}
return sb.toString();
} /*
* private static byte[] parseHexStr2Byte(String hexStr) { if
* (hexStr.length() < 1) return null; byte[] result = new
* byte[hexStr.length()/2]; for (int i = 0;i< hexStr.length()/2; i++) { int
* high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16); int low =
* Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16); result[i] = (byte)
* (high * 16 + low); } return result; }
*/ private static byte[] tohash256Deal(String datastr) {
try {
MessageDigest digester = MessageDigest.getInstance("SHA-256");
digester.update(datastr.getBytes());
byte[] hex = digester.digest();
return hex;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e.getMessage());
}
} /**
* 生成隨機金鑰
*
* @param size
* 位數
* @return
*/
public static String generateRandomKey(int size) {
StringBuilder key = new StringBuilder();
String chars = "0123456789ABCDEF";
for (int i = 0; i < size; i++) {
int index = (int) (Math.random() * (chars.length() - 1));
key.append(chars.charAt(index));
}
return key.toString();
} public static void main(String[] args) { String content = "123456";
String password = generateRandomKey(32);
System.out.println("明文:" + content);
System.out.println("key:" + password); byte[] encryptResult = AES256Util.encrypt(content, password);
System.out.println(encryptResult);
System.out.println("密文:" + AES256Util.parseByte2HexStr(encryptResult)); String decryptResult = AES256Util.decrypt(encryptResult, password);
System.out.println("解密:" + decryptResult);
}
}
3.2.2非對稱加密
3.2.2.1概述

package cn.mars.app.txn.zjyl; import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map; import javax.crypto.Cipher; /**
* Rsa工具類
*
* @author ThinkPad
*
*/
public abstract class RsaUtils {
/**
* 生成公鑰私鑰對,使用預設模長1024。
*
* @return Object[] : 0:公鑰( RSAPublicKey ),1:私鑰( RSAPrivateKey )
*/ private static final int DEFAULT_KEY_LEN = 2048; public static Map<String, String> genKeyPair() {
return genKeyPair(DEFAULT_KEY_LEN); } /**
* 指定模長生成公私鑰對
*
* @param modulus
* @return
*/
public static Map<String, String> genKeyPair(int modulus) {
KeyPairGenerator keyPairGen;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
keyPairGen.initialize(modulus);
KeyPair keyPair = keyPairGen.generateKeyPair(); Map<String, String> keyMaps = new HashMap<String, String>();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
keyMaps.put("publicKey", new String(Base64.encode(publicKey.getEncoded())));
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
keyMaps.put("privateKey", new String(Base64.encode(privateKey.getEncoded()))); return keyMaps;
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
} /**
* 公鑰加密
*
* @param publicKeyBytes
* @param data
* @param modulus
* 公鑰模長,範圍512-2048。
* @return
*/
public static byte[] encryptByPublicKey(byte[] publicKeyBytes, byte[] data, int modulus) {
try {
// RSA最大加密明文大小
int maxEncryptBlock = modulus / 8 - 11; X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxEncryptBlock) {
cache = cipher.doFinal(data, offSet, maxEncryptBlock);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxEncryptBlock;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
} catch (Exception e) {
throw new RuntimeException(e);
} } /**
* 公鑰加密,金鑰模長使用預設長度1024。
*
* @param publicKeyBytes
* 公鑰RSAPublicKey getEncoded()
* @param data
* 要加密的位元組陣列
*/
public static byte[] encryptByPublicKey(byte[] publicKeyBytes, byte[] data) {
return encryptByPublicKey(publicKeyBytes, data, DEFAULT_KEY_LEN);
} /**
* 公鑰解密
*
* @param publicKeyBytes
* 公鑰RSAPublicKey getEncoded()
* @param encryptedData
* 被(私鑰)加密過的位元組陣列
* @param modulus
* 模長,範圍512-2048
* @return
*/
public static byte[] decryptByPublicKey(byte[] publicKeyBytes, byte[] encryptedData, int modulus) {
// RSA最大解密密文大小
int maxDecryptBlock = modulus / 8;
try {
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 對資料分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxDecryptBlock) {
cache = cipher.doFinal(encryptedData, offSet, maxDecryptBlock);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxDecryptBlock;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 公鑰解密,預設模長1024
*
* @param publicKeyBytes
* 公鑰RSAPublicKey getEncoded()
* @param encryptedData
* 被(私鑰)加密過的位元組陣列
*/
public static byte[] decryptByPublicKey(byte[] publicKeyBytes, byte[] encryptedData) {
return decryptByPublicKey(publicKeyBytes, encryptedData, DEFAULT_KEY_LEN);
} /**
* 私鑰加密
*
* @param privateKeyBytes
* 私鑰RSAPrivateKey getEncoded()
* @param data
* 要加密的位元組陣列
* @param modulus
* 模長,範圍512-2048。
*/
public static byte[] encryptByPrivateKey(byte[] privateKeyBytes, byte[] data, int modulus) {
try {
// RSA最大加密明文大小
int maxEncryptBlock = modulus / 8 - 11; PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxEncryptBlock) {
cache = cipher.doFinal(data, offSet, maxEncryptBlock);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxEncryptBlock;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 私鑰加密,預設模長1024。
*
* @param privateKeyBytes
* 私鑰RSAPrivateKey getEncoded()
* @param data
* 要加密的位元組陣列
*/
public static byte[] encryptByPrivateKey(byte[] privateKeyBytes, byte[] data) {
return encryptByPrivateKey(privateKeyBytes, data, DEFAULT_KEY_LEN);
} /**
* 私鑰解密
*
* @param privateKeyBytes
* 私鑰RSAPrivateKey getEncoded()
* @param encryptedData
* 被(公鑰)加密過的位元組陣列
* @param modulus
* 模長,範圍512-2048
*/
public static byte[] decryptByPrivateKey(byte[] privateKeyBytes, byte[] encryptedData, int modulus) {
try {
// RSA最大解密密文大小
int maxDecryptBlock = modulus / 8; PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > maxDecryptBlock) {
cache = cipher.doFinal(encryptedData, offSet, maxDecryptBlock);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * maxDecryptBlock;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 私鑰解密,預設模長1024。
*
* @param privateKeyBytes
* 私鑰RSAPrivateKey getEncoded()
* @param encryptedData
* 被(公鑰)加密過的位元組陣列
*/
public static byte[] decryptByPrivateKey(byte[] privateKeyBytes, byte[] encryptedData) {
return decryptByPrivateKey(privateKeyBytes, encryptedData, DEFAULT_KEY_LEN);
} public static void main(String[] args) {
genKeyPair();
}
}
此文只是簡單介紹了java常用的加減密演算法,之後文章會對每種演算法做具體說明。