Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 12674|回复: 0

[JavaEE] javax.crypto.BadPaddingException: Given final block not properly padded 解决方法

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-1-17 23:59:59 | 显示全部楼层 |阅读模式
    下面的 Des 加密解密代码,在加密时正常,但是在解密是抛出错误:

    1. javax.crypto.BadPaddingException: Given final block not properly padded
    2.         at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    3.         at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
    4.         at com.sun.crypto.provider.DESCipher.engineDoFinal(DashoA13*..)
    5.         at javax.crypto.Cipher.doFinal(DashoA13*..)
    复制代码
    1. public class Des {
    2.     static Des instance;
    3.     static Key key;
    4.     static Cipher encryptCipher;
    5.     static Cipher decryptCipher;

    6.     protected Des() {
    7.     }

    8.     protected Des(String strKey) {
    9.         key = setKey(strKey);
    10.         try {
    11.             encryptCipher = Cipher.getInstance("DES");
    12.             encryptCipher.init(Cipher.ENCRYPT_MODE, key);
    13.             decryptCipher = Cipher.getInstance("DES");
    14.             decryptCipher.init(Cipher.DECRYPT_MODE, key);
    15.         } catch (NoSuchAlgorithmException e) {
    16.             e.printStackTrace();
    17.         } catch (NoSuchPaddingException e) {
    18.             e.printStackTrace();
    19.         } catch (InvalidKeyException e) {
    20.             e.printStackTrace();
    21.         }

    22.     }

    23.     public static Des getInstance() {
    24.         if (instance == null) {
    25.             instance = new Des("diaxxxxoft@201Y10");
    26.         }

    27.         return instance;
    28.     }

    29.     //  根据参数生成KEY
    30.     private Key setKey(String strKey) {
    31.         try {
    32.             KeyGenerator _generator = KeyGenerator.getInstance("DES");
    33.             _generator.init(new SecureRandom(strKey.getBytes()));
    34.             return _generator.generateKey();

    35.         } catch (Exception e) {
    36.             e.printStackTrace();
    37.         }

    38.         return null;
    39.     }

    40.     //  加密String明文输入,String密文输出
    41.     public String setEncString(String strMing) {
    42.         BASE64Encoder base64en = new BASE64Encoder();
    43.         try {
    44.             byte[] byteMing = strMing.getBytes("UTF-8");
    45.             byte[] byteMi = this.getEncCode(byteMing);
    46.             return base64en.encode(byteMi);
    47.         } catch (Exception e) {
    48.             e.printStackTrace();
    49.         }
    50.         return null;
    51.     }

    52.     //加密以byte[]明文输入,byte[]密文输出
    53.     private byte[] getEncCode(byte[] byteS) {
    54.         byte[] byteFina = null;
    55.         try {
    56.             byteFina = encryptCipher.doFinal(byteS);
    57.         } catch (Exception e) {
    58.             e.printStackTrace();
    59.         }
    60.         return byteFina;
    61.     }

    62.     //         解密:以String密文输入,String明文输出
    63.     public String setDesString(String strMi) {
    64.         BASE64Decoder base64De = new BASE64Decoder();
    65.         try {
    66.             byte[] byteMi = base64De.decodeBuffer(strMi);
    67.             byte[] byteMing = this.getDesCode(byteMi);
    68.             return new String(byteMing, "UTF-8");
    69.         } catch (Exception e) {
    70.             e.printStackTrace();
    71.         }
    72.         return null;
    73.     }

    74.     // 解密以byte[]密文输入,以byte[]明文输出
    75.     private byte[] getDesCode(byte[] byteD) {
    76.         byte[] byteFina = null;
    77.         try {
    78.             byteFina = decryptCipher.doFinal(byteD);
    79.         } catch (Exception e) {
    80.             e.printStackTrace();
    81.         }
    82.         return byteFina;
    83.     }

    84.     //多线程测试一下
    85.     public static void main(String[] args) throws InterruptedException {

    86.         //没有依赖注入的配置,所以在这里手动生成一次
    87.         Des dtDes = Des.getInstance();

    88.         final String[] mi = new String[10];
    89.         for (int i = 0; i < 10; i++) {
    90.             final Integer integer = i;
    91.             Thread thread = new Thread() {
    92.                 public void run() {
    93.                     //明文加密:
    94.                     Des dtDes = Des.getInstance();
    95.                     mi[integer] = dtDes.setEncString("ShowHistory.jsp?MenuId=345&MenuBelong=1&tableLimits=where a1450=RecordId"); //调用get函数获取加密后密文。
    96.                 }
    97.             };
    98.             thread.start();
    99.         }

    100.         Thread.sleep(5000);

    101.         for (int i = 0; i < 10; i++) {
    102.             final Integer integer = i;

    103.             Thread thread2 = new Thread() {
    104.                 public void run() {
    105.                     System.out.println(String.format("mi[%s] = %s", integer, mi[integer]));
    106.                     //这样来模拟另外一个页面的获取
    107.                     Des dtDes2 = Des.getInstance();
    108.                     String M = dtDes2.setDesString(mi[integer]);//调用get函数获取解密后明文。
    109.                     System.out.println(String.format("des[%s] = %s", integer, M));
    110.                 }
    111.             };
    112.             thread2.start();
    113.         }

    114.         //等待打印完毕
    115.         Thread.sleep(5000);
    116.     }
    117. }
    复制代码


    解决方法:
    将 setKey方法修改为如下:
    1.     //  根据参数生成KEY
    2.     private Key setKey(String strKey) {
    3.         try {
    4.             SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
    5.             DESKeySpec keySpec = new DESKeySpec(strKey.getBytes("utf-8"));  
    6.             keyFactory.generateSecret(keySpec);  
    7.             return keyFactory.generateSecret(keySpec);
    8.         } catch (Exception e) {
    9.             e.printStackTrace();
    10.         }

    11.         return null;
    12.     }
    复制代码


    不使用SecureRandom生成SecretKey,而是使用SecretKeyFactory;重新实现方法generateKey,代码如下
    问题解决。

    另外如果 加密时  和解密 时使用的秘钥 不一样,也会报 相同的错误。
    比如加密时使用的秘钥:
    diaxxxxoft@201xxxx10
    而解密时使用的秘钥:
    addddxxxx
    那么在解密时也可能会报这个错误。

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-24 19:06 , Processed in 0.359445 second(s), 38 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表