RSA加密长度限制问题解决 BadPaddingException
程序员文章站
2024-03-14 14:42:28
...
Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:380)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:291)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
at javax.crypto.Cipher.doFinal(Cipher.java:2223)
at com.asymmetric.rsa.TestRSA.testDecrypt(TestRSA.java:115)
at com.asymmetric.rsa.TestRSA.main(TestRSA.java:34)
RSA加密支持长度117,解密支持最大长度128【同事测试结果】
RSA可以用公钥加密,私钥解密,同时也可以用私钥加密,公钥解密;
直接贴工具类
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
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;
/**
* SecurityUtil简介
*
* @author zengdezheng3
* @date 2020-02-20 19:29
*/
public class SecurityUtil {
private final static Logger log = Logger.getLogger(SecurityUtil.class);
private String secretKey;//加解***
private String charetSet = "utf-8";
/**
* 加密算法RSA
*/
private static final String KEY_ALGORITHM = "RSA";
/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;
/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;
/**
* 常量0
*/
private static final int ZERO = 0;
public SecurityUtil(){
}
public SecurityUtil(String secretKey) {
this.setSecretKey(secretKey);
}
public void setSecretKey(String secretKey) {
this.secretKey = secretKey;
}
public void setCharetSet(String charetSet) {
this.charetSet = charetSet;
}
/**
* AES加密
*
* @param str
* @return
*/
public String encryptStrWithAes(String str) {
String resStr = null;
try {
byte[] raw = secretKey.getBytes(charetSet);
SecretKeySpec key = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] byteContent = str.getBytes(charetSet);
byte[] encrypted = cipher.doFinal(byteContent);
BASE64Encoder encoder = new BASE64Encoder();
resStr = encoder.encode(encrypted);
} catch (Exception e) {
log.error("AES加密失败", e);
throw new RuntimeException("AES加密失败",e) ;
}
return resStr;
}
/**
* AES解密
*
* @param str
* @return
*/
public String decryptStrWithAes(String str) {
String resStr = null;
try {
byte[] raw = secretKey.getBytes(charetSet);
SecretKeySpec key = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
BASE64Decoder decoder = new BASE64Decoder();
byte[] decrypted = cipher.doFinal(decoder.decodeBuffer(str));
resStr = new String(decrypted, charetSet);
} catch (Exception e) {
log.error("AES解密失败", e);
throw new RuntimeException("AES解密失败",e) ;
}
return resStr;
}
public String aesEncode(String str){
String resStr = null;
try {
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(secretKey.getBytes(charetSet));
KeyGenerator kGen = KeyGenerator.getInstance("AES");
kGen.init(128, random);
SecretKey secretKey = kGen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器
byte[] byteContent = str.getBytes("utf-8");
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(byteContent);
BASE64Encoder encoder = new BASE64Encoder();
resStr= encoder.encode(result);
} catch (Exception e){
e.printStackTrace();
}
return resStr;
}
public String aesDecode(String str){
String resStr = null;
try {
KeyGenerator kGen = KeyGenerator.getInstance("AES");
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
random.setSeed(secretKey.getBytes());
kGen.init(128, random);
SecretKey secretKey = kGen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
BASE64Decoder decoder = new BASE64Decoder();
byte[] decrypted = cipher.doFinal(decoder.decodeBuffer(str));
resStr = new String(decrypted, charetSet);
} catch (Exception e){
e.printStackTrace();
}
return resStr;
}
/**
* 随机生成**对
* @throws NoSuchAlgorithmException
*/
public static void genKeyPair() 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 = new String(Base64.encodeBase64(publicKey.getEncoded()));
// 得到私钥字符串
String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
// 将公钥和私钥保存到Map
System.out.println("公钥:" + publicKeyString);
System.out.println("私钥:" + privateKeyString);
}
/**
* RSA公钥加密
* @param str
* @param publicKey
* @return
* @throws Exception
*/
public static String encrypt( String str, String publicKey ) throws Exception{
//base64编码的公钥
byte[] decoded = Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
//RSA加密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
}
/**
* RSA私钥解密
* @param str
* @param privateKey
* @return
* @throws Exception
*/
public static String decrypt(String str, String privateKey) throws Exception{
//64位解码加密后的字符串
byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
//base64编码的私钥
byte[] decoded = Base64.decodeBase64(privateKey);
RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
//RSA解密
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
return new String(cipher.doFinal(inputByte));
}
/**
* 公钥加密
*
* @param content 源数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static String encryptByPublicKey(String content, String publicKey)
throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
byte[] data = content.getBytes(StandardCharsets.UTF_8);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
byte[] encrypt = encrypt(data, KeyFactory.getInstance(KEY_ALGORITHM), keyFactory.generatePublic(x509KeySpec));
return Base64.encodeBase64String(encrypt);
}
/**
* 私钥加密
*
* @param content 源数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static String encryptByPrivateKey(String content, String privateKey)
throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
byte[] data = content.getBytes(StandardCharsets.UTF_8);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
byte[] encrypt = encrypt(data, keyFactory, privateK);
return Base64.encodeBase64String(encrypt);
}
/**
* 私钥解密
*
* @param content 已加密数据
* @param privateKey 私钥(BASE64编码)
* @return
* @throws Exception
*/
public static String decryptByPrivateKey(String content, String privateKey)
throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
//64位解码加密后的字符串
byte[] encryptedData = Base64.decodeBase64(content.getBytes(StandardCharsets.UTF_8));
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
return new String(decrypt(encryptedData, keyFactory, keyFactory.generatePrivate(pkcs8KeySpec)));
}
/**
* 公钥解密
*
* @param content 已加密数据
* @param publicKey 公钥(BASE64编码)
* @return
* @throws Exception
*/
public static String decryptByPublicKey(String content, String publicKey)
throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
//64位解码加密后的字符串
byte[] encryptedData = Base64.decodeBase64(content.getBytes(StandardCharsets.UTF_8));
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
return new String(decrypt(encryptedData, keyFactory, publicK));
}
/**
* 解密公共方法
*/
private static byte[] decrypt(byte[] data, KeyFactory keyFactory, Key key) throws Exception {
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, key);
return encryptAndDecrypt(data, cipher, MAX_DECRYPT_BLOCK);
}
/**
* 加密公共方法
*/
private static byte[] encrypt(byte[] data, KeyFactory keyFactory, Key key) throws Exception {
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, key);
return encryptAndDecrypt(data, cipher, MAX_ENCRYPT_BLOCK);
}
/**
* 加密解密分段处理公共方法
*/
private static byte[] encryptAndDecrypt(byte[] data, Cipher cipher, int maxSize) throws Exception {
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = ZERO;
byte[] cache;
int i = ZERO;
// 对数据分段加密
while (inputLen - offSet > ZERO) {
if (inputLen - offSet > maxSize) {
cache = cipher.doFinal(data, offSet, maxSize);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, ZERO, cache.length);
i++;
offSet = i * maxSize;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
public static String decryptRSADefault(String privateKeyStr,String data) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] privateKeyArray = privateKeyStr.getBytes();
byte[] dataArray = data.getBytes();
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyArray));
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return new String(cipher.doFinal(Base64.decodeBase64(dataArray)), StandardCharsets.UTF_8);
}
/**
* @param args
*/
public static void main(String[] args) {
try {
/*genKeyPair();*/
String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrqdHrXcgPbVvJkVfV9yyWfOsQiMSWtZRz40GUDjhiLmW6lsrU5" +
"HixbIc69O6ms4LL3joYnFvkvTRAkBbuMTRY6aaup6Cpsg+9HDFS6qlSPeq53VlTkoIZ990QvSL6fMyT/mwt7T66QevU8cXUHv3RT4Sbj5TclIwr2PXiom84mwIDAQAB";
String privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOup0etdyA9tW8mRV9X3LJZ86xCIxJa1lHPjQZQOOGIuZbqWytTke" +
"LFshzr07qazgsveOhicW+S9NECQFu4xNFjppq6noKmyD70cMVLqqVI96rndWVOSghn33RC9Ivp8zJP+bC3tPrpB69TxxdQe/dFPhJuPlNyUjCvY9eKibzibAgM" +
"BAAECgYAnJ9MqIS3halEq34xRj70Hz/+agq7vP4JH8wVtXSN/JKhgZTeUQdXP3PFnGVUhu4fK6cSLXEdkbQ9mfspgjypcHeV+lTzqR52oiuPEiMJPHFsSNYslorL" +
"ONmSWHyFGZAQe9H6Tl02GuIkSAXeruPYIHkx8WBGsIIwUeO3vRyXtUQJBAP033/PF8yAQwOJ6nnthcaaeSfu9zovPicKZ6P+5gXdBQYXX61cLqDX3gnyASZyrkgRn7" +
"FiZqZF2HPitPLJ+w+MCQQDuQJNYn7zt09E2fEvNjzWobt2oilpn/rDPzEzeaSGg1soxWt7KLWFqNfL+t++iUvlj+Kzx3I+o36HQK32vroXpAkABh7DmvC935iIEPFFw1" +
"WnmY9Z2mvMAjUR71Io/4VMS8WX/9QoLAJsHmHNFZVEMjUzYkfgvoN4RbvFF32YafgGZAkAAgG5O/3ccYRfNr5FRS33nbuRUmIX8NhMVPO7kgQArIIiodfKGJnZQDPEID" +
"Eca5mXUChADKl27E0157L2FAy8RAkAmnqO1yH+jN0dYccz6CibH0ReTjFNddojHqMxzl/ohDlCBTtn3RPHnzVz4U7iOh15Ka4JCVh+mMYtVoA9rgZwl";
String content = "aRiSY6lzi0k/VfnSRc25R31pp4rEHfx633+E/vUF7yzzD9Gdblgn295jdvHn4eSB/uuDpYmwNQkpjYpaMCXJOJ6f2/Pp3uJEvurgnOOOoGw6OUHEUQh3YCYngWGi8jbwtXs0D5OZw1S6zQQAFWMMpzReMdEt67DcNOqvIe68xmCVTvfJhnW7lzFRrtcMe2w8ia8vYLJwlfr2fA1OfJlI+h6obEyVSFJhISTmccfkCCNqbZNnlzow2jA+NMkGoLnXXdOAnWspo7E/OV2mKkOhXxmFsUTCPE4ToC41N47VLn6Lc7byyYyMhPO4ZsmFI1tZAH01OiF+hMGgaHGzhHySpQ==";
String decrypt = decryptByPrivateKey(content,privateKey);
System.out.println("解密结果:" + decrypt);
} catch (Exception e) {
e.printStackTrace();
}
}
}
下一篇: Android AES加解密