你的位置:首页 > Java教程

[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("diantusoft@20150310");    }    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,代码如下

问题解决。