zoukankan      html  css  js  c++  java
  • javax.crypto.BadPaddingException: Given final block not properly padded 解决方法

    下面的 Des 加密解密代码,在加密时正常,但是在解密是抛出错误:

    javax.crypto.BadPaddingException: Given final block not properly padded
            at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
            at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
            at com.sun.crypto.provider.DESCipher.engineDoFinal(DashoA13*..)
            at javax.crypto.Cipher.doFinal(DashoA13*..)
    

     

    public class Des {
        static Des instance;
        static Key key;
        static Cipher encryptCipher;
        static Cipher decryptCipher;
    
        protected Des() {
        }
    
        protected Des(String strKey) {
            key = setKey(strKey);
            try {
                encryptCipher = Cipher.getInstance("DES");
                encryptCipher.init(Cipher.ENCRYPT_MODE, key);
                decryptCipher = Cipher.getInstance("DES");
                decryptCipher.init(Cipher.DECRYPT_MODE, key);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            }
    
        }
    
        public static Des getInstance() {
            if (instance == null) {
                instance = new Des("diaxxxxoft@201Y10");
            }
    
            return instance;
        }
    
        //  根据参数生成KEY
        private Key setKey(String strKey) {
            try {
                KeyGenerator _generator = KeyGenerator.getInstance("DES");
                _generator.init(new SecureRandom(strKey.getBytes()));
                return _generator.generateKey();
    
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        //  加密String明文输入,String密文输出
        public String setEncString(String strMing) {
            BASE64Encoder base64en = new BASE64Encoder();
            try {
                byte[] byteMing = strMing.getBytes("UTF-8");
                byte[] byteMi = this.getEncCode(byteMing);
                return base64en.encode(byteMi);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        //加密以byte[]明文输入,byte[]密文输出
        private byte[] getEncCode(byte[] byteS) {
            byte[] byteFina = null;
            try {
                byteFina = encryptCipher.doFinal(byteS);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return byteFina;
        }
    
        //	 解密:以String密文输入,String明文输出
        public String setDesString(String strMi) {
            BASE64Decoder base64De = new BASE64Decoder();
            try {
                byte[] byteMi = base64De.decodeBuffer(strMi);
                byte[] byteMing = this.getDesCode(byteMi);
                return new String(byteMing, "UTF-8");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        // 解密以byte[]密文输入,以byte[]明文输出
        private byte[] getDesCode(byte[] byteD) {
            byte[] byteFina = null;
            try {
                byteFina = decryptCipher.doFinal(byteD);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return byteFina;
        }
    
        //多线程测试一下
        public static void main(String[] args) throws InterruptedException {
    
            //没有依赖注入的配置,所以在这里手动生成一次
            Des dtDes = Des.getInstance();
    
            final String[] mi = new String[10];
            for (int i = 0; i < 10; i++) {
                final Integer integer = i;
                Thread thread = new Thread() {
                    public void run() {
                        //明文加密:
                        Des dtDes = Des.getInstance();
                        mi[integer] = dtDes.setEncString("ShowHistory.jsp?MenuId=345&MenuBelong=1&tableLimits=where a1450=RecordId"); //调用get函数获取加密后密文。
                    }
                };
                thread.start();
            }
    
            Thread.sleep(5000);
    
            for (int i = 0; i < 10; i++) {
                final Integer integer = i;
    
                Thread thread2 = new Thread() {
                    public void run() {
                        System.out.println(String.format("mi[%s] = %s", integer, mi[integer]));
                        //这样来模拟另外一个页面的获取
                        Des dtDes2 = Des.getInstance();
                        String M = dtDes2.setDesString(mi[integer]);//调用get函数获取解密后明文。
                        System.out.println(String.format("des[%s] = %s", integer, M));
                    }
                };
                thread2.start();
            }
    
            //等待打印完毕
            Thread.sleep(5000);
        }
    }
    

    解决方法:

    将 setKey方法修改为如下:

        //  根据参数生成KEY
        private Key setKey(String strKey) {
            try {
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
                DESKeySpec keySpec = new DESKeySpec(strKey.getBytes("utf-8"));  
                keyFactory.generateSecret(keySpec);  
                return keyFactory.generateSecret(keySpec); 
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            return null;
        }
    

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

    问题解决。

    另外如果 加密时  和解密 时使用的秘钥 不一样,也会报 相同的错误。

    比如加密时使用的秘钥:

    diaxxxxoft@201xxxx10

    而解密时使用的秘钥:

    addddxxxx

    那么在解密时也可能会报这个错误。

  • 相关阅读:
    Evensgn 的债务
    Passward
    拯救莫莉斯
    文艺平衡树
    Fliptile 翻格子游戏
    Making the Grade (bzoj1592)
    紧急疏散evacuate
    Password
    [NOIP2015]斗地主
    运输问题1
  • 原文地址:https://www.cnblogs.com/digdeep/p/5580244.html
Copyright © 2011-2022 走看看