加密算法---RSA 非对称加密原理及使用
一 非对称加密原理介绍
非对称加密算法中,有两个密钥:公钥和私钥。它们是一对,如果用公钥进行加密,只有用对应的私钥才能解密;如果用私钥进行加密,只有用对应的公钥才能解密。
非对称加密算法实现机密信息的交换过程为:甲方生成一对密钥并将其中一个作为公钥向其他方公开;得到该公钥的乙方使用该密钥对机密信息进行加密后发送给甲方;甲方再用自己的另一个专用密钥对加密后的信息进行解密。
最有名的非对称加密算法当属 RSA 了,本文将对 RSA 算法的加/解密过程进行详细剖析。
非对称加密拥有两把密钥。
RSA —— 经典的非对称加密算法
二 加密解密测试
2.1 加密解密工具类
import lombok.extern.slf4j.Slf4j;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class EncryptUtils {
/**
* sha 加密
*
* @param str
* @return
*/
public static String sha(String str) {
String sha256Str = "";
try {
MessageDigest sha256Deget = MessageDigest.getInstance("SHA-256");
byte[] sha256Encode = sha256Deget.digest(str.getBytes());
sha256Str = ByteToHexStr(sha256Encode);
} catch (Exception e) {
log.info("FRLOG:SHA256加密异常::", e.getMessage());
}
return sha256Str;
}
/**
* byte数组转16进制字符串
*
* @param bytes
* @return
*/
private static String ByteToHexStr(byte[] bytes) {
String hexStr = "";
for (int i = 0; i < bytes.length; i++) {
int temp = bytes[i] & 0xff;
String tempHex = Integer.toHexString(temp);
if (tempHex.length() < 2) {
hexStr += "0" + tempHex;
} else {
hexStr += tempHex;
}
}
return hexStr;
}
/**--------------------------对称加密aes----------------------------------*/
/**
* aes 加密
*
* @param str
* @param privateKey
* @return
*/
public static String aesEncrypt(String str, String privateKey) {
try {
// 生成密钥对象
SecretKey secKey = generateAesKey(privateKey.getBytes());
// 获取 AES 密码器
Cipher cipher = Cipher.getInstance("AES");
// 初始化密码器(加密模型)
cipher.init(Cipher.ENCRYPT_MODE, secKey);
// 加密数据, 返回密文
byte[] cipherBytes = cipher.doFinal(str.getBytes());
// return new BASE64Encoder().encodeBuffer(cipherBytes);
return Base64.getEncoder().encodeToString(cipherBytes);
} catch (Throwable e) {
log.info("aes 加密异常", e.getMessage());
}
return null;
}
/**
* aes 解密
*
* @param str
* @param privateKey
* @return
*/
public static String aesDecrypt(String str, String privateKey) {
try {
// 生成密钥对象
SecretKey secKey = generateAesKey(privateKey.getBytes());
// 获取 AES 密码器
Cipher cipher = Cipher.getInstance("AES");
// 初始化密码器(加密模型)
cipher.init(Cipher.DECRYPT_MODE, secKey);
byte[] decode = Base64.getDecoder().decode(str);
// 加密数据, 返回密文
byte[] cipherBytes = cipher.doFinal(decode);
return new String(cipherBytes);
} catch (Throwable e) {
log.info("aes 解密异常 ", e.getMessage());
}
return null;
}
/**
* 生成密钥对象
*/
private static SecretKey generateAesKey(byte[] key) throws Exception {
// 创建安全随机数生成器
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
// 设置 密钥key的字节数组 作为安全随机数生成器的种子
random.setSeed(key);
// 创建 AES算法生成器
KeyGenerator gen = KeyGenerator.getInstance("AES");
// 初始化算法生成器
gen.init(128, random);
// 生成 AES密钥对象, 也可以直接创建密钥对象: return new SecretKeySpec(key, ALGORITHM);
return gen.generateKey();
}
/**-------------------------- base64加密 ----------------------------------*/
/**
* base64加密
*
* @param key
* @return
*/
public static String base64Encode(byte[] key) {
String result = Base64.getEncoder().encodeToString(key);
return result;
}
/**
* base64解密
*
* @param key
* @return
*/
public static byte[] base64DecodeB(String key) {
byte[] result = null;
result = Base64.getDecoder().decode(key);
return result;
}
/**
* 是否被base64加密过
*
* @param str
* @return
*/
public static boolean isBase64(String str) {
if (str == null || str.trim().length() == 0) {
return false;
} else {
if (str.length() % 4 != 0) {
return false;
}
char[] strChars = str.toCharArray();
for (char c : strChars) {
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '+' || c == '/' || c == '=') {
continue;
} else {
return false;
}
}
return true;
}
}
/**-------------------------- 对称加密des ----------------------------------*/
/**
* des加密
*
* @param datasource
* @param password
* @return
*/
public static String desEncrypt(String datasource, String password) {
try {
SecureRandom random = new SecureRandom();
DESKeySpec desKey = new DESKeySpec(password.getBytes());
// 创建一个密匙工厂,然后用它把DESKeySpec转换成
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(desKey);
// Cipher对象实际完成加密操作
Cipher cipher = Cipher.getInstance("DES");
// 用密匙初始化Cipher对象
cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
// 现在,获取数据并加密
// 正式执行加密操作
return base64Encode(cipher.doFinal(datasource.getBytes()));
} catch (Throwable e) {
log.info("des 加密异常", e.getMessage());
}
return null;
}
/**
* des 解密
*
* @param src
* @param password
* @return
* @throws Exception
*/
public static String desDecrypt(String src, String password) {
try {
// DES算法要求有一个可信任的随机数源
SecureRandom random = new SecureRandom();
// 创建一个DESKeySpec对象
DESKeySpec desKey = new DESKeySpec(password.getBytes("UTF-8"));
// 创建一个密匙工厂
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
// 将DESKeySpec对象转换成SecretKey对象
SecretKey securekey = keyFactory.generateSecret(desKey);
// Cipher对象实际完成解密操作
Cipher cipher = Cipher.getInstance("DES");
// 用密匙初始化Cipher对象
cipher.init(Cipher.DECRYPT_MODE, securekey, random);
// 真正开始解密操作
return new String(cipher.doFinal(base64DecodeB(src)));
} catch (Throwable e) {
log.info("des 解密异常", e.getMessage());
}
return null;
}
/**-------------------------- 非对称加密RSA ----------------------------------*/
/**
* 随机生成RSA密钥对
*
* @return privateKey, publicKey
* @throws NoSuchAlgorithmException
*/
public static Map<String, String> genRSAKeyPair() throws NoSuchAlgorithmException {
// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
// 初始化密钥对生成器,密钥大小为96-1024位
keyPairGen.initialize(1024, new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到私钥
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
// 得到公钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
String publicKeyString = base64Encode(publicKey.getEncoded());
// 得到私钥字符串
String privateKeyString = base64Encode(privateKey.getEncoded());
// 将公钥和私钥保存到Map
Map<String, String> result = new HashMap<String, String>();
result.put("publicKey", publicKeyString.replaceAll("\n", "").replace("\r", "").trim());
result.put("privateKey", privateKeyString.replaceAll("\n", "").replace("\r", "").trim());
return result;
}
/**
* rsa 加密
*
* @param str
* @param publicKey
* @return
* @throws Exception
*/
public static String rsaEncrypt(String str, String publicKey) throws Exception {
//base64编码的公钥
byte[] decoded = base64DecodeB(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
//RSA加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = base64Encode(cipher.doFinal(str.getBytes("UTF-8")));
return outStr;
}
/**
* rsa解密
*
* @param str
* @param privateKey
* @return
* @throws Exception
*/
public static String rsaDecrypt(String str, String privateKey) throws Exception {
//64位解码加密后的字符串
byte[] inputByte = base64DecodeB(str);
//base64编码的私钥
byte[] decoded = base64DecodeB(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
String outStr = new String(cipher.doFinal(inputByte));
return outStr;
}
}
2.2 测试
1、生成公钥私钥
2、用公钥加密、私钥解密
@Test
void rsaTest() throws Exception {
//生成公钥私钥
Map<String, String> keys = EncryptUtils.genRSAKeyPair();
String publicKey = keys.get("publicKey");
String privateKey = keys.get("privateKey");
System.out.println(publicKey);
System.out.println(privateKey);
Map<String, java.io.Serializable> map = new HashMap<>(2);
map.put("username", "xiamaofa");
map.put("timestamp", 111111111);
//公钥加密
String encrypt = EncryptUtils.rsaEncrypt(map.toString(), publicKey);
//私钥解密
String decrypt = EncryptUtils.rsaDecrypt(encrypt, privateKey);
System.out.println(encrypt);
System.out.println(decrypt);
}
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtzSxX6dlQZoF9nH6zC8pffKAdzZTa8DuJ5a3Vvp5B6+zRgRObF234Za2FpAjiC8MMVKHekXfhxZhRROTB+1POsGS0lyR+JoBbYRb+ou+LNXKkP9wCsMRl4wbkM4wc4A1uFmnxQKm66VUV7ZxNXKh6ID/N/atkEriNCFiBYWzC6wIDAQAB
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAK3NLFfp2VBmgX2cfrMLyl98oB3NlNrwO4nlrdW+nkHr7NGBE5sXbfhlrYWkCOILwwxUod6Rd+HFmFFE5MH7U86wZLSXJH4mgFthFv6i74s1cqQ/3AKwxGXjBuQzjBzgDW4WafFAqbrpVRXtnE1cqHogP839q2QSuI0IWIFhbMLrAgMBAAECgYArKc1deAI0aYC3RWph5Qe5dyX8wNW7GfZvZM8rSk/bZ1BFJ51K4yK4kefqTLa4DNu/8DTTJaV0OLJ/XHDDjDtfqzTsWzaHhhTbrqhw0NfZ7YcxSzMQmiEyC35pAY420Ba1vILyeHBZm7z3I2qhhmCrGI+mDL+MiHJaqgAcJarmYQJBAPp1zD4mZuehg0t8T8UUcASn7f0t1RFwU+5d6wa9DaxS1AWgK4Yj0v0scGlD50dMI5xWWnWjHrR1jz/qyYskCIUCQQCxpU3jzMkYjKZTksObuNZG+62agPIWFUdL6mWT4Bp9kRzAb3Fen4r+/iJFVv/0/O+hYDF29Q/T7gHuAgmJCjCvAkAEkR9PRs37jUNinfqqYkwEmbdKNYq8DatKHmZJsirMqJn7HEeO45pWSXgnQzi1YRsJH734hSfrLHWXOcXBBsAtAkEAoPWLho1F5FWEWxMO46jtljFyUhzlvLaY/CMs2Hjk58M1DvOrADaE5Zh0iulST7NimJClIQjYx4jO/M2hwCaYhwJAVzgz6a9DKv7KctpaBu/l8EJtoY8C1iBVQ4QxfB3HxmM+O01InjZf7lE1FIuYFjIIRwdiCStFN0NyMJnC27/Dmg==
cmjRO+bvz0bPW5TSRTVSbLnQdyI0ITWHGiTErf8ufepnscpHsOr8ax2wmSIHsKBb6r0ysD0dcWV4I1R02rqmdSoPc/JlT4V6yhQ20ZlumiSZ8GIn+rN3aQ8exmQp3f8Sh10mmTOwtMmLS8Vd++HutAEThn26b87jJ6R4e82uS4k=
{username=xiamaofa, timestamp=111111111}