下面的 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 那么在解密时也可能会报这个错误。
|