javax.crypto.BadPaddingException: Given final block not

 

现象描述:

windows上加解密正常,linux上加密正常,解密时发生如下异常:

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.AESCipher.engineDoFinal(DashoA13*..)
       at javax.crypto.Cipher.doFinal(DashoA13*..)
       at chb.test.crypto.AESUtils.crypt(AESUtils.java:386)
       at chb.test.crypto.AESUtils.AesDecrypt(AESUtils.java:254)
       at chb.test.crypto.AESUtils.main(AESUtils.java:40) 

解决方法:

经过检查之后,定位在生成KEY的方法上,如下:

  1. public static SecretKey getKey (String strKey) {
  2.          try {         
  3.             KeyGenerator _generator = KeyGenerator.getInstance( "AES" );
  4.             _generator.init(128, new SecureRandom(strKey.getBytes()));
  5.                 return _generator.generateKey();
  6.         }  catch (Exception e) {
  7.              throw new RuntimeException( " 初始化密钥出现异常 " );
  8.         }
  9.       } 

复制代码

修改到如下方式,问题解决:

  1.   public static SecretKey getKey(String strKey) {
  2.          try {         
  3.             KeyGenerator _generator = KeyGenerator.getInstance( "AES" );
  4.              SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );
  5.             secureRandom.setSeed(strKey.getBytes());
  6.             _generator.init(128,secureRandom);
  7.                 return _generator.generateKey();
  8.         }  catch (Exception e) {
  9.              throw new RuntimeException( " 初始化密钥出现异常 " );
  10.         }
  11.       } 

复制代码

原因分析
SecureRandom 实现完全隨操作系统本身的內部狀態,除非調用方在調用 getInstance 方法之後又調用了 setSeed 方法;该实现在 windows 上每次生成的 key 都相同,但是在 solaris 或部分 linux 系统上则不同。

原因二:

1、加密完byte[] 后,需要将加密了的byte[] 转换成base64保存,如: 
BASE64Encoder base64encoder = new BASE64Encoder(); 
String encode=base64encoder.encode(bytes); 

2、解密前,需要将加密后的字符串从base64转回来再解密,如: 
BASE64Decoder base64decoder = new BASE64Decoder(); 
byte[] encodeByte = base64decoder.decodeBuffer(str); 


完整例子:

  1. package com.travelsky.tdp.pkgStock.util;
  2.  
  3. import java.io.IOException;
  4. import java.io.UnsupportedEncodingException;
  5. import java.security.InvalidKeyException;
  6. import java.security.NoSuchAlgorithmException;
  7. import java.security.SecureRandom;
  8.  
  9. import javax.crypto.BadPaddingException;
  10. import javax.crypto.Cipher;
  11. import javax.crypto.IllegalBlockSizeException;
  12. import javax.crypto.KeyGenerator;
  13. import javax.crypto.NoSuchPaddingException;
  14. import javax.crypto.SecretKey;
  15. import javax.crypto.spec.SecretKeySpec;
  16.  
  17. import sun.misc.BASE64Decoder;
  18. import sun.misc.BASE64Encoder;
  19.  
  20. public class SecurityAES {
  21.         private final static String encoding = "UTF-8"; 
  22.         /**
  23.          * AES加密
  24.          * 
  25.          * @param content
  26.          * @param password
  27.          * @return
  28.          */
  29.         public static String encryptAES(String content, String password) {
  30.                 byte[] encryptResult = encrypt(content, password);
  31.                 String encryptResultStr = parseByte2HexStr(encryptResult);
  32.                 // BASE64位加密
  33.                 encryptResultStr = ebotongEncrypto(encryptResultStr);
  34.                 return encryptResultStr;
  35.         }
  36.  
  37.         /**
  38.          * AES解密
  39.          * 
  40.          * @param encryptResultStr
  41.          * @param password
  42.          * @return
  43.          */
  44.         public static String decrypt(String encryptResultStr, String password) {
  45.                 // BASE64位解密
  46.                 String decrpt = ebotongDecrypto(encryptResultStr);
  47.                 byte[] decryptFrom = parseHexStr2Byte(decrpt);
  48.                 byte[] decryptResult = decrypt(decryptFrom, password);
  49.                 return new String(decryptResult);
  50.         }
  51.  
  52.                 /**
  53.          * 加密字符串
  54.          */
  55.         public static String ebotongEncrypto(String str) {
  56.                 BASE64Encoder base64encoder = new BASE64Encoder();
  57.                 String result = str;
  58.                 if (str != null && str.length() > 0) {
  59.                         try {
  60.                                 byte[] encodeByte = str.getBytes(encoding);
  61.                                 result = base64encoder.encode(encodeByte);
  62.                         } catch (Exception e) {
  63.                                 e.printStackTrace();
  64.                         }
  65.                 }
  66.                 //base64加密超过一定长度会自动换行 需要去除换行符
  67.                 return result.replaceAll("\r\n", "").replaceAll("\r", "").replaceAll("\n", "");
  68.         }
  69.  
  70.         /**
  71.          * 解密字符串
  72.          */
  73.         public static String ebotongDecrypto(String str) {
  74.                 BASE64Decoder base64decoder = new BASE64Decoder();
  75.                 try {
  76.                         byte[] encodeByte = base64decoder.decodeBuffer(str);
  77.                         return new String(encodeByte);
  78.                 } catch (IOException e) {
  79.                         e.printStackTrace();
  80.                         return str;
  81.                 }
  82.         }
  83.         /**  
  84.          * 加密  
  85.          *   
  86.          * @param content 需要加密的内容  
  87.          * @param password  加密密码  
  88.          * @return  
  89.          */  
  90.         private static byte[] encrypt(String content, String password) {   
  91.                 try {              
  92.                         KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
  93.                         //防止linux下 随机生成key
  94.                         SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );   
  95.                         secureRandom.setSeed(password.getBytes());   
  96.                         kgen.init(128, secureRandom);
  97.                         //kgen.init(128, new SecureRandom(password.getBytes()));   
  98.                         SecretKey secretKey = kgen.generateKey();   
  99.                         byte[] enCodeFormat = secretKey.getEncoded();   
  100.                         SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");   
  101.                         Cipher cipher = Cipher.getInstance("AES");// 创建密码器   
  102.                         byte[] byteContent = content.getBytes("utf-8");   
  103.                         cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化   
  104.                         byte[] result = cipher.doFinal(byteContent);   
  105.                         return result; // 加密   
  106.                 } catch (NoSuchAlgorithmException e) {   
  107.                         e.printStackTrace();   
  108.                 } catch (NoSuchPaddingException e) {   
  109.                         e.printStackTrace();   
  110.                 } catch (InvalidKeyException e) {   
  111.                         e.printStackTrace();   
  112.                 } catch (UnsupportedEncodingException e) {   
  113.                         e.printStackTrace();   
  114.                 } catch (IllegalBlockSizeException e) {   
  115.                         e.printStackTrace();   
  116.                 } catch (BadPaddingException e) {   
  117.                         e.printStackTrace();   
  118.                 }   
  119.                 return null;   
  120.         }  
  121.  
  122.  
  123.         /**解密  
  124.          * @param content  待解密内容  
  125.          * @param password 解密密钥  
  126.          * @return  
  127.          */  
  128.         private static byte[] decrypt(byte[] content, String password) {   
  129.                 try {   
  130.                          KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
  131.                        //防止linux下 随机生成key
  132.                              SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );   
  133.                              secureRandom.setSeed(password.getBytes());   
  134.                              kgen.init(128, secureRandom);
  135.                          //kgen.init(128, new SecureRandom(password.getBytes()));   
  136.                          SecretKey secretKey = kgen.generateKey();   
  137.                          byte[] enCodeFormat = secretKey.getEncoded();   
  138.                          SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");               
  139.                          Cipher cipher = Cipher.getInstance("AES");// 创建密码器   
  140.                         cipher.init(Cipher.DECRYPT_MODE, key);// 初始化   
  141.                         byte[] result = cipher.doFinal(content);   
  142.                         return result; // 加密   
  143.                 } catch (NoSuchAlgorithmException e) {   
  144.                         e.printStackTrace();   
  145.                 } catch (NoSuchPaddingException e) {   
  146.                         e.printStackTrace();   
  147.                 } catch (InvalidKeyException e) {   
  148.                         e.printStackTrace();   
  149.                 } catch (IllegalBlockSizeException e) {   
  150.                         e.printStackTrace();   
  151.                 } catch (BadPaddingException e) {   
  152.                         e.printStackTrace();   
  153.                 }   
  154.                 return null;   
  155.         }  
  156.  
  157.         /**将二进制转换成16进制  
  158.          * @param buf  
  159.          * @return  
  160.          */  
  161.         public static String parseByte2HexStr(byte buf[]) {   
  162.                 StringBuffer sb = new StringBuffer();   
  163.                 for (int i = 0; i < buf.length; i++) {   
  164.                         String hex = Integer.toHexString(buf[i] & 0xFF);   
  165.                         if (hex.length() == 1) {   
  166.                                 hex = '0' + hex;   
  167.                         }   
  168.                         sb.append(hex.toUpperCase());   
  169.                 }   
  170.                 return sb.toString();   
  171.         }  
  172.  
  173.  
  174.         /**将16进制转换为二进制  
  175.          * @param hexStr  
  176.          * @return  
  177.          */  
  178.         public static byte[] parseHexStr2Byte(String hexStr) {   
  179.                 if (hexStr.length() < 1)   
  180.                         return null;   
  181.                 byte[] result = new byte[hexStr.length()/2];   
  182.                 for (int i = 0;i< hexStr.length()/2; i++) {   
  183.                         int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);   
  184.                         int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);   
  185.                         result[i] = (byte) (high * 16 + low);   
  186.                 }   
  187.                 return result;   
  188.         }  
  189.  
  190.  
  191.         
  192. }
  193.  

复制代码

 

 

改为如下代码

 

 


以上在linux测试ok 原文转自:http://konglx.iteye.com/blog/954085

   KeyGenerator kgen = KeyGenerator.getInstance("AES");

//         kgen.init(128, new SecureRandom(password.getBytes()));

           //防止linux下 随机生成key 

            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );  

            secureRandom.setSeed(password.getBytes());  

    // 根据密钥初始化密钥生成器 

   kgen.init(128, secureRandom); 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值