Java的RSA分段解密
前言
加密的公私钥可以用工具类的generateRsaKey方法调用,也可以随便找个网站生成,本工具类生成的2048长度的秘钥,可以修改,如果修改了生成长度,记得把工具类前面的几个参数改了,加密分段长度计算方法:长度/8-11。
一.调用
解密
Map<String, Object> resMap = new HashMap<>();
String encipher = RsaEncry.encipher(JSON.toJSONString(resMap));
System.out.println("加密后数据:" + encipher);
解密
String decipher = RsaEncry.decipher(data);
System.out.println("解密后数据:" + decipher);
二.工具类
package com.kaiwei.management.untils;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
/**
* author: CD
* Data: 2024-01-05 09:54:56 星期五
* Description: rsa加解密
*/
public class RsaEncry {
private static final int DEFAULT_RSA_KEY_SIZE = 2048;//生成密钥对长度
private static final int ENSEGMENTSIZE = 245;//加密分段长度
private static final int DESEGMENTSIZE = 256;//解密分段长度
private static final String KEY_ALGORITHM = "RSA";
static String publicRsaKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgsoD4g7tFPFVb/zjrhTIFqeZswoWhUTHxvOVn/ElCE35qdtdODKfABcVsFfLMmS/MdN1ZKN8MYFNThGgQODKdABNhy+FVNkdtR74m0u7i36nuCGHO+XhbzsimptaLD1HZC4AotVQGNd3mZx9D6rncfZeGxU0voZuQn9bN9UaYzOtNmNDH9uR+ZZA6asGxkPWjpHHJcF+GiSyP2kxQa5Mp1qkYqR5W+4KeLZZ1zOqs7Gzq1ubn0bexvHwR3wqqXebhppeY+tzL9zs8G6Jukwktvpw0ETd90hpPMIieW0pv2Tx6aVaCq3Nms08CL7X7xuUSf40qGYX2DB6J5dRksF3IwIDAQAB";
static String privateRsaKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCCygPiDu0U8VVv/OOuFMgWp5mzChaFRMfG85Wf8SUITfmp2104Mp8AFxWwV8syZL8x03Vko3wxgU1OEaBA4Mp0AE2HL4VU2R21HvibS7uLfqe4IYc75eFvOyKam1osPUdkLgCi1VAY13eZnH0Pqudx9l4bFTS+hm5Cf1s31RpjM602Y0Mf25H5lkDpqwbGQ9aOkcclwX4aJLI/aTFBrkynWqRipHlb7gp4tlnXM6qzsbOrW5ufRt7G8fBHfCqpd5uGml5j63Mv3Ozwbom6TCS2+nDQRN33SGk8wiJ5bSm/ZPHppVoKrc2azTwIvtfvG5RJ/jSoZhfYMHonl1GSwXcjAgMBAAECggEAJDoiszYhM2DZoohw5GI7PhM0fqQ3srhngdMsyb243UED+6mYe52B7zt1tX/L9+xyDTIeXT7vgqLnL82wDuh1C4ad8ukVzHfLQ8UNZa6nhy8Q8+7Nj6jQNcgygJKxenmK0dPwNypQ4mCkbzcqaPGU5Dsyu9u23WNNHTw7nw53HazitbcMLS5xAOjMM+ZxDlHwFIAnCDQV7cmJVd43yRO7z5sBwT4lVP7OqkHWZvM+9mlcUi1ObP6imlN8ENKGtmucV3s2/I/Bc9hdofkvcU3L05OulhGf9YulPvNO4Hfp8emZsQf28Qf7oqCZofHdXYlkSnQqP6H18hmaiDAnHkEfOQKBgQD/EEF8oY8TFrIFbZWs/oeLWVHJP2me2qxbRSZktQn2kGoLDw5nvT1+7Ez+8fRhq3dGI+f0xZkEbkhPQAxyFHF/J7Ye8K6M83ELoHAyP2tndAsUD/P3gg3R+kArQ1wCpUwmXvWCzEIzpwSSlbP+IW2dYPDvA7cMSexaabSZmc8vNwKBgQCDRPLxZ1E+206pRpkjRyoaaF4ils3oKZOgRqGoBSdAACOPS9TQ8cr2ruJ8Jt7TkHsI1KranaUAl6uyUG+ZxOzM6q4sPvMzRMli1nni9Z8TsIRoY6Hjv3SDHPzT6omqZbS6+geg2eK+JPgygKFKUgiWsTM5xZ+4ycUxo/vqTEm1dQKBgQDCJ76hv11ou2rxxNQdpnbJNUmTdsjQmkZ/B2lNWZ3m6VE/b8uYXi4Uko2dt9I+EsatRqHH6i4reENkyC1xHWyzzSfN74n/U0RnBE7DgREh4+yW7fnZG0+n2eXEyPaeMPOBdeFPGmr+ZJGPf5NOzGVjWiqs1lgda5wVyscl8TYMCwKBgC0jHUKC2z343RB51Rh7VO/lqVDNeBn3ieqXvuhudTOdmJyiX5hFPBwcwIYeO4qV6Kh9sA4iHOWaQZC79dPzEdXYcHGIZ8neQj05MIopGT0E+lKGx9jvMVoQMqOPxyyPcljEtrDJmxz0y19aOZu7n3ZpkgqweJ5qyuKp12qWNtYtAoGBAJTUEaZP0H8cGAGlL9cJjM3jK671JtOoK4+SFss6KZYq2Qp40mfI2nmM2Y5Tmg72Tj+B8F0+b+9aLvGYN/DtmrX7UREGnMggmmmOw/Bwk9U5WiBMUWvc0HIqJ7+52AymZVqq9lJW7ZkmAClPBwoLCm5a9BxyB9iy1huSPjcBY4ku";
//生成RSA 公私钥,可选长度为1025,2048位
public static Map<String,String> generateRsaKey(int keySize) {
Map<String,String> result = new HashMap<>(2);
try {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
// 初始化密钥对生成器,密钥大小为1024 2048位
keyPairGen.initialize(keySize, new SecureRandom());
// 生成一个密钥对,保存在keyPair中
KeyPair keyPair = keyPairGen.generateKeyPair();
// 得到公钥字符串
result.put("publicKey", new String(Base64.encodeBase64(keyPair.getPublic().getEncoded())));
// 得到私钥字符串
result.put("privateKey", new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded())));
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
return result;
}
//将公钥转换为base64格式
public static PublicKey getPublicKey(String publicKeyBase64)
throws InvalidKeySpecException, NoSuchAlgorithmException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec publicpkcs8KeySpec =
new X509EncodedKeySpec(Base64.decodeBase64(publicKeyBase64));
PublicKey publicKey = keyFactory.generatePublic(publicpkcs8KeySpec);
return publicKey;
}
//将私钥转换为base64格式
public static PrivateKey getPrivateKey(String privateKeyBase64)
throws NoSuchAlgorithmException, InvalidKeySpecException{
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec privatekcs8KeySpec =
new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyBase64));
PrivateKey privateKey = keyFactory.generatePrivate(privatekcs8KeySpec);
return privateKey;
}
//分段加密
public static String encipher(String ciphertext){
try {
int segmentSize = ENSEGMENTSIZE;
PublicKey publicKey = getPublicKey(publicRsaKey);
// 用公钥加密
byte[] srcBytes = ciphertext.getBytes();
// Cipher负责完成加密或解密工作,基于RSA
Cipher cipher = Cipher.getInstance("RSA");
// 根据公钥,对Cipher对象进行初始化
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] resultBytes = null;
if(segmentSize>0) {
resultBytes = cipherDoFinal(cipher, srcBytes, segmentSize); //分段加密
}
else {
resultBytes = cipher.doFinal(srcBytes);
}
String base64Str = Base64.encodeBase64String(resultBytes);
return base64Str;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//分段解密
public static String decipher(String contentBase64){
try {
int segmentSize = DESEGMENTSIZE;
PrivateKey privateKey = getPrivateKey(privateRsaKey);
// 用私钥解密
byte[] srcBytes = Base64.decodeBase64(contentBase64);
// Cipher负责完成加密或解密工作,基于RSA
Cipher deCipher = Cipher.getInstance("RSA");
// 根据公钥,对Cipher对象进行初始化
deCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decBytes = null;//deCipher.doFinal(srcBytes);
if(segmentSize>0) {
decBytes = cipherDoFinal(deCipher, srcBytes, segmentSize); //分段加密
}
else {
decBytes = deCipher.doFinal(srcBytes);
}
String decrytStr=new String(decBytes);
return decrytStr;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
//分段大小
private static byte[] cipherDoFinal(Cipher cipher, byte[] srcBytes, int segmentSize)
throws IllegalBlockSizeException, BadPaddingException, IOException {
if(segmentSize<=0){
throw new RuntimeException("分段大小必须大于0");
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int inputLen = srcBytes.length;
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解密
while (inputLen - offSet > 0) {
if (inputLen - offSet > segmentSize) {
cache = cipher.doFinal(srcBytes, offSet, segmentSize);
} else {
cache = cipher.doFinal(srcBytes, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * segmentSize;
}
byte[] data = out.toByteArray();
out.close();
return data;
}
}