代码
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
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.HashMap;
import java.util.Map;
@Slf4j
public class RSAUtils {
public static final String RSA = "RSA";// 非对称加密密钥算法
public static final String ECB_PADDING = "RSA/ECB/PKCS1Padding";// 加密填充方式
/**
* RSA算法规定:待加密的字节数不能超过密钥的长度值除以8再减去11。 而加密后得到密文的字节数,正好是密钥的长度值除以 8。
* 密钥位数
*/
private static final int KEY_SIZE = 1024;
private static final int RESERVE_BYTES = 11;
/**
* RSA最大解密密文大小
*/
private static final int DECRYPT_BLOCK = KEY_SIZE / 8;
/**
* RSA最大加密明文大小117
*/
private static final int ENCRYPT_BLOCK = DECRYPT_BLOCK - RESERVE_BYTES;
/**
* 私钥
*/
private static final String privateKeyString = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIsQBZlv8j8RfDoD5NtKYgfQSEmFE49IF1etuE0KuYugtv0yNs9oj3CnkScw93qIF9A5yoqC755IYSGwKYrPnHgas473opeb//jysizI0F2gR2bQ23/kLykXVZoRkmhvO8Gr+OdaJ4ja1F7you97onNKrN70ixeylFkOzi0gpsgTAgMBAAECgYAL38Zan7Bzqi6NVZ/JCcTtHd/OR0qwRVuY5QCDs5K8VXDKlesQMsFswSIn0oqPL+e4o/ajdSK4xT1l/wDNFYUqq13rPfSCAK45xjSEBLpNTP/o/l8xa9lha69KFYN6rCTCsSQaES++/u6a/BchsdTVkP+M3JxfBYBVKclOlSaj4QJBAOaNws0n+GXhvSfROjyKHZJvRLznd5v62WiMpAhXhmmcVCUmehpRIHlT7legUzLmAW77MxGx+3J4HnP7WdC1zP0CQQCaaTNgeMtB0aHhSA0GOJ3Gm0o7Gqb58LsMQmJUACKiSUs4jvDCOZQs6TRHeI5VPyApaawPzoONiy4/Zkv4yH5PAkBfud53JjBpxOev/5xphIMwyMhGkujDt8zLLxHwcL7bXNBHOImcIbEVDzc35NaGnJ9dwCj9IOQhLCSgzW0GTmXVAkBmuIFzNiiRerHkOphfgR6E1x3Ev/BA6cKlXywmkYh4yaV+1KiZrNBEKEedHDgjwcDVi/To9wtRCDwV9SmpMUfFAkEAzWjcOaSmMB+WaMCuYEggsbPW9KUXw8kP/Vi061S3r6E6AcLG2vyWvms8LsMhH9acXm5QoeUnwcN0LI63tYqoEw==";
/**
* 公钥
*/
private static final String publicKeyString = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLEAWZb/I/EXw6A+TbSmIH0EhJhROPSBdXrbhNCrmLoLb9MjbPaI9wp5EnMPd6iBfQOcqKgu+eSGEhsCmKz5x4GrOO96KXm//48rIsyNBdoEdm0Nt/5C8pF1WaEZJobzvBq/jnWieI2tRe8qLve6JzSqze9IsXspRZDs4tIKbIEwIDAQAB";
/**
* 生成密钥
*/
public static Map<Integer, String> genKeyPair() {
Map<Integer, String> keyMap = new HashMap<>(); // 用于封装随机产生的公钥与私钥
try {
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = generateKeyPair(512);
assert keyPair != null;
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
// 得到公钥字符串
String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
// 得到私钥字符串
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
// 将公钥和私钥保存到Map
keyMap.put(0, publicKeyString); // 0表示公钥
keyMap.put(1, privateKeyString); // 1表示私钥
} catch (Exception e) {
log.info("生成公钥私钥异常:" + e.getMessage());
return null;
}
System.out.println(JSON.toJSONString(keyMap, JSONWriter.Feature.PrettyFormat));
return keyMap;
}
public static void main(String[] args) throws Exception {
String s = "13241234";
String s1 = encrypt(s);
System.out.println("加密后:" + s1);
System.out.println("解密后:" + decrypt(s1));
}
/**
* 随机生成RSA密钥对
*
* @param keySize 密钥长度,范围:512-2048,一般2048
*/
public static KeyPair generateKeyPair(int keySize) {
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(keySize);
return kpg.genKeyPair();
} catch (Exception e) {
log.error("generateKeyPair exception.", e);
return null;
}
}
/**
* 读取私钥
* @throws Exception 返回私钥的key对象
*/
private static String getPrivateKey() throws Exception {
//创建key的工厂
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//创建私钥key的规则
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyString));
//返回私钥对象
return new String(Base64.encodeBase64(keyFactory.generatePrivate(keySpec).getEncoded()));
}
/**
* 读取公钥
*
* @return 公钥字符传
* @throws Exception 返回公钥的key对象
*/
private static String getPublicKey() throws Exception {
//创建key的工厂
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
//创建公钥key的规则
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyString));
//返回公钥对象
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return new String(Base64.encodeBase64(publicKey.getEncoded()));
}
public static PublicKey getPublicKey(byte[] key) throws Exception {
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
return keyFactory.generatePublic(keySpec);
}
public static PrivateKey getPrivateKey(byte[] key) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key);
KeyFactory keyFactory = KeyFactory.getInstance(RSA);
return keyFactory.generatePrivate(keySpec);
}
/**
* 公钥加密
*
* @param plain 加密的内容
*/
public static String encrypt(String plain) throws Exception {
byte[] data = plain.getBytes(StandardCharsets.UTF_8);
//得到公钥
String publicKey = getPublicKey();
byte[] key = Base64.decodeBase64(publicKey);
byte[] result = encryptWithPublicKeyBlock(data, key);
return Base64.encodeBase64String(result);
}
/**
* 私钥解密
*
* @param plain 解密的内容
*/
public static String decrypt(String plain) {
try {
byte[] data = Base64.decodeBase64(plain.getBytes(StandardCharsets.UTF_8));
String privateKey = getPrivateKey();
byte[] key = Base64.decodeBase64(privateKey);
byte[] bytes = decryptWithPrivateKeyBlock(data, key);
return new String(bytes);
} catch (Exception e) {
log.error("decryptWithPrivateKeyBlock exception.", e);
}
return "";
}
public static byte[] encryptWithPublicKeyBlock(byte[] data, byte[] key) throws Exception {
Cipher cipher = Cipher.getInstance(ECB_PADDING);
cipher.init(Cipher.ENCRYPT_MODE, getPublicKey(key));
int inputLength = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
while (inputLength - offset > 0) {
if (inputLength - offset > ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offset, ENCRYPT_BLOCK);
} else {
//防止传入的data 长度过长 进行分片处理
cache = cipher.doFinal(data, offset, inputLength - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * ENCRYPT_BLOCK;
}
byte[] bos = out.toByteArray();
out.close();
return bos;
}
public static byte[] decryptWithPrivateKeyBlock(byte[] data, byte[] key) throws Exception {
int blockCount = (data.length / DECRYPT_BLOCK);
if ((data.length % DECRYPT_BLOCK) != 0) {
blockCount += 1;
}
ByteArrayOutputStream bos = new ByteArrayOutputStream(blockCount * DECRYPT_BLOCK);
Cipher cipher = Cipher.getInstance(ECB_PADDING);
cipher.init(Cipher.DECRYPT_MODE, getPrivateKey(key));
for (int offset = 0; offset < data.length; offset += DECRYPT_BLOCK) {
int inputLen = (data.length - offset);
if (inputLen > DECRYPT_BLOCK) {
inputLen = DECRYPT_BLOCK;
}
byte[] decryptedBlock = cipher.doFinal(data, offset, inputLen);
bos.write(decryptedBlock);
}
bos.close();
return bos.toByteArray();
}
}