1、加密算法的分類
對稱加密算法:使用一個密鑰,即可加密,也可解密。
非對稱加密算法:使用一對密鑰,公鑰只能加密不能解密,只有私鑰可以用來解密。運算速度不及對稱加密算法。
常見的加密算法:
算法名 | 分類 | 是否冪等 | 目前是否破解 | 破解年限 |
---|---|---|---|---|
RSA-155(512bit) | 非對稱加密 | 否 | 已被破解 | 1999年耗費5個月 |
RSA-786(786bit) | 非對稱加密 | 否 | 已被破解 | 2009年 |
RSA-1024(1024bit) | 非對稱加密 | 否 | 未被破解 | 預計這幾年 |
RSA-2048(2048bit) | 非對稱加密 | 否 | 未被破解 | |
RSA系列 | 非對稱加密 | 否 | … | 量子計算機 |
DES | 對稱加密 | 是 | 已被破解 | 1990年短時間內 |
AES | 對稱加密 | 是 | 未被破解 |
2、RSA 算法演示
需要選擇兩個質數:5 和 11
計算 n : 5 * 11 = 55
n = 11, 0111 因此 這個密鑰是 6 bit
計算 φ(n) = (5 - 1) * (11 - 1) = 40
選擇一個數 e 當作公鑰因子,需要滿足 1 < e < φ(n), 並且 e 和 φ(n) 互質:e = 13
得到公鑰 :(n = 35, e = 13)
計算私鑰因子 d,需要滿足 (e * d) mod φ(n) = 1。計算得出 d = 37
得到私鑰:(n = 55, d = 37)
加密公式:f(x) = (x ^ e) mod n
解密公式:f(x) = (x ^ d) mod n
對 20 進行加密,結果爲:(20 ^ 13) mod 55 = 25
對 25 進行解密,結果爲:(25 ^ 37) mod 55 = 20
public static void main(String[] args) {
rsa(20, 55, 13); // 加密, 25
rsa(25, 55, 37); // 解密, 20
}
/**
*
* @param x 待加密或解密的值
* @param n
* @param e 密鑰因子
*/
public static void rsa(int x, int n, int e) {
int sum = x;
for (int i = 1; i < e; i++) {
sum = sum * x;
if (sum > n)
sum = sum % n;
}
System.out.println(sum);
}
3、使用工具生成 RSA 密鑰
使用 openSSL 工具生成私鑰
openssl genrsa -out rsa_pri.key 1024
使用 openssl 根據私鑰生成公鑰
openssl rsa -in rsa_pri.key -pubout -out rsa_pub.key
生成的私鑰編碼爲 pkcs12, Java 不能直接使用,需要轉成 pkcs8 格式
openssl pkcs8 -topk8 -inform PEM -in rsa_pri.key -outform PEM -nocrypt
4、Java加解密
package zh.utils;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.Cipher;
public class RSA {
public static void main(String[] args) throws Exception {
String priKeyStr = "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANg9tNBlqb0rIAKXzkFOZ8+Uk3qOLaqXpqBSeiV/YOiAlWe5lI7U7RAiV/vHabsm0jRWz+UdsSgMOfUaJmAjAMvdqPEua3mJo5rGNkeBqop42bj0XLGDcyd562HwV1yaZDGQrAREqLrsDIcSc3R9ULl+9R/m9MFpwK6mr5IkG6xBAgMBAAECgYEAl+kBlUVWMSaSnj+3Dfnew91Endw0CJvw2sAWPzF1CuEKFIwy6QR8ZdE6rg4xIODs2wgBlJt/UPsF3EI6o17ztviac/pCvu09au1eW1f2aHGRvLSHTVVpA6V7FcZvZsk0J+3dGWhv0VxnVrUGW2r/BBwouxoe4R3ZL/Mvi3YxM2ECQQD/UHrgAa9wATMiuBcmcPTZSDHjr9DbddTs9XmHpAGYSrODLpWBHfYX8yGMGQfEpaJFIRccScankF+OoRsfhDYvAkEA2NJdXpy3SKxePLrcHWI9XnpFxg4QDIfK11fiy7DspHJGNxkgnuz6OqxZ71l88z0tlU2Q8D6793dzGdaw0GMYjwJBANs8bIb2a4OuRA7ILXjg/h+mktCFJL+Oyyw/DgCfoI75dnRrCA47gBrIuEHpLHZ8FH9wDrxHzcINg0Cirvu9OBkCQGZUEgDfEZlY0Dj1L4EmpjP6nQd2B5kCVXcAYWcknuqVjBHg6AZZbVdXlDJkF5ZsnyDBtM/Nq8SFOWtOabBPtH0CQQCzVp0/Awzo7CYYXnQcK6qro8x9eDSB1eZ0DVuth36xh2CC2OKi2gjMiQBrs2se3W/TUaTiW546rCwTDTvSHqjs";
String pubKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYPbTQZam9KyACl85BTmfPlJN6ji2ql6agUnolf2DogJVnuZSO1O0QIlf7x2m7JtI0Vs/lHbEoDDn1GiZgIwDL3ajxLmt5iaOaxjZHgaqKeNm49Fyxg3Mneeth8FdcmmQxkKwERKi67AyHEnN0fVC5fvUf5vTBacCupq+SJBusQQIDAQAB";
String data = "this is rsa";
// 加載公鑰
RSAPublicKey pubKey = loadPublicKey(pubKeyStr);
// 加載私鑰
PrivateKey priKey = loadPrivateKey(priKeyStr);
// 使用公鑰加密
String sign = sign(pubKey, data);
System.out.println("加密結果爲:" + sign);
String decrypt = decrypt(priKey, sign);
System.out.println("解密結果爲:" + decrypt);
}
/**
* 公鑰加密過程
*
*/
public static String sign(RSAPublicKey publicKey, String data)
throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] output = cipher.doFinal(data.getBytes());
return Base64ByteToString(output);
}
//私鑰解密
public static String decrypt(PrivateKey privateKey, String data) throws Exception{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] bytes = cipher.doFinal(StringToBase64Byte(data));
return new String(bytes);
}
/**
* 從字符串中加載私鑰
*/
public static PrivateKey loadPrivateKey(String priStr) throws Exception{
byte[] keyBytes = StringToBase64Byte(priStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
/**
* 從字符串中加載公鑰
*/
public static RSAPublicKey loadPublicKey(String publicKeyStr)
throws Exception {
byte[] buffer = StringToBase64Byte(publicKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
}
/**
* 將byte[] 轉換成字符串
*/
public static String byte2Hex(byte[] srcBytes) {
StringBuilder hexRetSB = new StringBuilder();
for (byte b : srcBytes) {
String hexString = Integer.toHexString(0x00ff & b);
hexRetSB.append(hexString.length() == 1 ? 0 : "").append(hexString);
}
return hexRetSB.toString();
}
/**
* 將字符串轉爲 Base64 格式的 byte
*/
public static byte[] StringToBase64Byte(String str) {
return Base64.getDecoder().decode(str);
}
/**
* 將 Base64 格式的 byte 轉爲字符串
*/
public static String Base64ByteToString(byte[] bt) {
return Base64.getEncoder().encodeToString(bt);
}
}