程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> javax.crypto.BadPaddingException: Given final block not properly padded 解決方法,rubyblockgiven

javax.crypto.BadPaddingException: Given final block not properly padded 解決方法,rubyblockgiven

編輯:JAVA綜合教程

javax.crypto.BadPaddingException: Given final block not properly padded 解決方法,rubyblockgiven


下面的 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

那麼在解密時也可能會報這個錯誤。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved