zoukankan      html  css  js  c++  java
  • RSA解密时BadPaddingException解决方法

    工作的时候遇到程序需要进行RSA加密解密的部分,在写第一版测试的时候,出现了:

    1. Exception in thread "main" javax.crypto.BadPaddingException: Data must start with zero
    2. at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
    3. at sun.security.rsa.RSAPadding.unpad(Unknown Source)
    4. at com.sun.crypto.provider.RSACipher.a(DashoA13*..)
    5. at com.sun.crypto.provider.RSACipher.engineDoFinal(DashoA13*..)
    6. at javax.crypto.Cipher.doFinal(DashoA13*..)
    7. at com.pack.RSAUtils.decryptByPrivateKey(RSAUtils.java:164)
    8. at com.pack.RSATest.test(RSATest.java:47)
    9. at com.pack.RSATest.main(RSATest.java:26)

    
    

    
    这样一个错误,
    

    代码:

    1. package com.pack;
    2. import java.io.File;
    3. import java.util.Map;
    4. public class RSATest {
    5. static String publicKey;
    6. static String privateKey;
    7. static {
    8. try {
    9. Map<String, Object> keyMap = RSAUtils.genKeyPair();
    10. publicKey = RSAUtils.getPublicKey(keyMap);
    11. privateKey = RSAUtils.getPrivateKey(keyMap);
    12. System.err.println("公钥: " + publicKey);
    13. System.err.println("私钥: " + privateKey);
    14. } catch (Exception e) {
    15. e.printStackTrace();
    16. }
    17. }
    18. public static void main(String[] args) throws Exception {
    19. test();
    20. }
     
    1. static void test() throws Exception {
    2. System.err.println("公钥加密——私钥解密");
    3. String source = "<manifest xmlns:android="http://schemas.android.com/apk/res/android"";
    4. System.out.println("r加密前文字:rn" + source);
    5. byte[] data = source.getBytes();
    6. byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);
    7. System.out.println("加密后文字:rn" + new String(encodedData));
    8. String str = new String(encodedData);
    9.        byte[] decodedData = RSAUtils.decryptByPrivateKey(str.getBytes(), privateKey);
    10. String target = new String(decodedData);
    11. System.out.println("解密后文字: rn" + target);
    12. }

    }
    

    但是如果我把加密后的byte数组直接解密,就没有问题,到网上找了很多,但是没有说的特别明白的帖子,后来在http://www.myexception.cn/java-other/BadPaddingException.html这里 看到了一个还算说的明白的帖子,

    其实就是因为把byte[]数组转化成字符串,写入到文件,但是从字符串转化成byte[]数组的时候,程序无法找到每一个byte[]里元素的临界点在哪里,所以知道了这一点,要解决这个问题也就简单了,就是在加密之后的byte[]元素之间加上一个标志符,可以使空格,也可以是0,.然后在解密的时候要进行字符串的拆分,组装成byte[]数组,然后再进行解密。就可以搞定了。

    所有就有了下面的方法:吐舌头

    1. package com.pack;
    2. import java.io.BufferedReader;
    3. import java.io.BufferedWriter;
    4. import java.io.File;
    5. import java.io.FileReader;
    6. import java.io.FileWriter;
    7. import java.io.IOException;
    8. import java.util.Map;
    9. /**
    10. * RSA对文件或字符串进行加密解密功�?
    11. * @author 胡松振
    12. *
    13. */
    14. public class RSAUtil {
    15. // 把byte[]元素之间添加空格,并转化成字符串返回,
    16. public String byteToString(byte[] resouce){
    17. StringBuffer sb = new StringBuffer();
    18. for (int i = 0; i < resouce.length; i++) {
    19. if (i == resouce.length-1) {
    20. sb.append(Byte.toString(resouce[i]));
    21. }else{
    22. sb.append(Byte.toString(resouce[i]));
    23. sb.append(" ");
    24. }
    25. }
    26. return sb.toString();
    27. }
    28. // 把字符串按照空格进行拆分成数组,然后转化成byte[],返回
    29. public byte[] stringToByte(String resouce){
    30. String[] strArr = resouce.split(" ");
    31. int len = strArr.length;
    32. byte[] clone = new byte[len];
    33. for (int i = 0; i < len; i++) {
    34. clone[i] = Byte.parseByte(strArr[i]);
    35. }
    36. return clone;
    37. }
    38. }

    
    

    
    

    那下面就是见证奇迹的时刻了:

    1. static void test() throws Exception {
    2. RSAUtil ru = new RSAUtil();
    3. System.err.println("公钥加密——私钥解密");
    4. String source = "<manifest xmlns:android="http://schemas.android.com/apk/res/android"";
    5. System.out.println("r加密前文字:rn" + source);
    6. byte[] data = source.getBytes();
    7. byte[] encodedData = RSAUtils.encryptByPublicKey(data, publicKey);
    8. System.out.println("加密后文字:rn" + new String(encodedData));
    9. String str = ru.byteToString(encodedData);
    10. byte[] resource = ru.stringToByte(str);
    11. byte[] decodedData = RSAUtils.decryptByPrivateKey(resource, privateKey);
    12. String target = new String(decodedData);
    13. System.out.println("解密后文字: rn" + target);
    14. }

    
    

    
    

    下面的结果就正确了:

    1. 加密前文字:
    2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    3. 加密后文字:
    4. 殞獒郵L崭'34?︱}库珃??茕y?曘肭蚐?堏?'d/B眅@XJD=w?桠嫟O褫?鄾埔4 ?w?8I嵀鶮)0+�镔霉暺`趕Yu侼桝?两�?1
    5. 解密后文字:
    6. <manifest xmlns:android="http://schemas.android.com/apk/res/android"




  • 相关阅读:
    js-20170816-Date对象
    js-20170804-Math对象
    js-20170619-string对象
    微信web开发者工具
    前端开发指南
    接口调试工具DHC
    CSS预处理器
    Weex
    Vue.js
    hbuilder
  • 原文地址:https://www.cnblogs.com/LoveShare/p/13232375.html
Copyright © 2011-2022 走看看