RSA解密时BadPaddingException解决方法
工作的时候遇到程序需要进行RSA加密解密的部分,在写第一版测试的时候,出现了:
Exception in thread "main" javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
at com.pack.RSAUtils.decryptByPrivateKey(RSAUtils.java:164)
at com.pack.RSATest.test(RSATest.java:47)
at com.pack.RSATest.main(RSATest.java:26)
这样一个错误,
代码:
package com.pack;
import java.io.File;
import java.util.Map;
public class RSATest {
static String publicKey;
static String privateKey;
static {
try {
Map<String, Object> keyMap = RSAUtils.genKeyPair();
publicKey = RSAUtils.getPublicKey(keyMap);
privateKey = RSAUtils.getPrivateKey(keyMap);
System.err.println("公钥: \n\r" + publicKey);
System.err.println("私钥: \n\r" + privateKey);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
test();
}
static void test() throws Exception {
System.err.println("公钥加密——私钥解密");
String source = "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"";
System.out.println("\r加密前文字:\r\n" + source);
byte[] data = source.getBytes();
byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);
System.out.println("加密后文字:\r\n" + new String(encodedData));
String str = new String(encodedData);
byte[] decodedData = RSAUtils.decryptByPrivateKey(str.getBytes(), privateKey);
String target = new String(decodedData);
System.out.println("解密后文字: \r\n" + target);
}
}
但是如果我把加密后的byte数组直接解密,就没有问题,到网上找了很多,但是没有说的特别明白的帖子,后来在http://www.myexception.cn/java-other/BadPaddingException.html这里 看到了一个还算说的明白的帖子,
其实就是因为把byte[]数组转化成字符串,写入到文件,但是从字符串转化成byte[]数组的时候,程序无法找到每一个byte[]里元素的临界点在哪里,所以知道了这一点,要解决这个问题也就简单了,就是在加密之后的byte[]元素之间加上一个标志符,可以使空格,也可以是0,.然后在解密的时候要进行字符串的拆分,组装成byte[]数组,然后再进行解密。就可以搞定了。
所有就有了下面的方法:
package com.pack;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Map;
/**
* RSA对文件或字符串进行加密解密功�?
* @author 胡松振
*
*/
public class RSAUtil {
// 把byte[]元素之间添加空格,并转化成字符串返回,
public String byteToString(byte[] resouce){
StringBuffer sb = new StringBuffer();
for (int i = 0; i < resouce.length; i++) {
if (i == resouce.length-1) {
sb.append(Byte.toString(resouce[i]));
}else{
sb.append(Byte.toString(resouce[i]));
sb.append(" ");
}
}
return sb.toString();
}
// 把字符串按照空格进行拆分成数组,然后转化成byte[],返回
public byte[] stringToByte(String resouce){
String[] strArr = resouce.split(" ");
int len = strArr.length;
byte[] clone = new byte[len];
for (int i = 0; i < len; i++) {
clone[i] = Byte.parseByte(strArr[i]);
}
return clone;
}
}
那下面就是见证奇迹的时刻了:
static void test() throws Exception {
RSAUtil ru = new RSAUtil();
System.err.println("公钥加密——私钥解密");
String source = "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"";
System.out.println("\r加密前文字:\r\n" + source);
byte[] data = source.getBytes();
byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);
System.out.println("加密后文字:\r\n" + new String(encodedData));
String str = ru.byteToString(encodedData);
byte[] resource = ru.stringToByte(str);
byte[] decodedData = RSAUtils.decryptByPrivateKey(resource, privateKey);
String target = new String(decodedData);
System.out.println("解密后文字: \r\n" + target);
}
下面的结果就正确了:
加密前文字:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
加密后文字:
殞獒郵L崭'34?︱}库珃??\茕y?曘肭蚐?堏?'d/B眅@XJ佗D=w?桠嫟O褫?鄾埔4 ?w?8I嵀鶮)0+镔霉暺`趕Y緤u侼桝?两?1鏷
解密后文字:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗