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);
}
}