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. import java.io.IOException;
  3. import java.io.UnsupportedEncodingException;
  4. import java.security.InvalidKeyException;
  5. import java.security.NoSuchAlgorithmException;
  6. import java.security.SecureRandom;

  7. import javax.crypto.BadPaddingException;
  8. import javax.crypto.Cipher;
  9. import javax.crypto.IllegalBlockSizeException;
  10. import javax.crypto.KeyGenerator;
  11. import javax.crypto.NoSuchPaddingException;
  12. import javax.crypto.SecretKey;
  13. import javax.crypto.spec.SecretKeySpec;

  14. import sun.misc.BASE64Decoder;
  15. import sun.misc.BASE64Encoder;

  16. public class SecurityAES {
  17.         private final static String encoding = "UTF-8"; 
  18.         /**
  19.          * AES加密
  20.          * 
  21.          * @param content
  22.          * @param password
  23.          * @return
  24.          */
  25.         public static String encryptAES(String content, String password) {
  26.                 byte[] encryptResult = encrypt(content, password);
  27.                 String encryptResultStr = parseByte2HexStr(encryptResult);
  28.                 // BASE64位加密
  29.                 encryptResultStr = ebotongEncrypto(encryptResultStr);
  30.                 return encryptResultStr;
  31.         }

  32.         /**
  33.          * AES解密
  34.          * 
  35.          * @param encryptResultStr
  36.          * @param password
  37.          * @return
  38.          */
  39.         public static String decrypt(String encryptResultStr, String password) {
  40.                 // BASE64位解密
  41.                 String decrpt = ebotongDecrypto(encryptResultStr);
  42.                 byte[] decryptFrom = parseHexStr2Byte(decrpt);
  43.                 byte[] decryptResult = decrypt(decryptFrom, password);
  44.                 return new String(decryptResult);
  45.         }

  46.                 /**
  47.          * 加密字符串
  48.          */
  49.         public static String ebotongEncrypto(String str) {
  50.                 BASE64Encoder base64encoder = new BASE64Encoder();
  51.                 String result = str;
  52.                 if (str != null && str.length() > 0) {
  53.                         try {
  54.                                 byte[] encodeByte = str.getBytes(encoding);
  55.                                 result = base64encoder.encode(encodeByte);
  56.                         } catch (Exception e) {
  57.                                 e.printStackTrace();
  58.                         }
  59.                 }
  60.                 //base64加密超过一定长度会自动换行 需要去除换行符
  61.                 return result.replaceAll("\r\n", "").replaceAll("\r", "").replaceAll("\n", "");
  62.         }

  63.         /**
  64.          * 解密字符串
  65.          */
  66.         public static String ebotongDecrypto(String str) {
  67.                 BASE64Decoder base64decoder = new BASE64Decoder();
  68.                 try {
  69.                         byte[] encodeByte = base64decoder.decodeBuffer(str);
  70.                         return new String(encodeByte);
  71.                 } catch (IOException e) {
  72.                         e.printStackTrace();
  73.                         return str;
  74.                 }
  75.         }
  76.         /**  
  77.          * 加密  
  78.          *   
  79.          * @param content 需要加密的内容  
  80.          * @param password  加密密码  
  81.          * @return  
  82.          */  
  83.         private static byte[] encrypt(String content, String password) {   
  84.                 try {              
  85.                         KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
  86.                         //防止linux下 随机生成key
  87.                         SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );   
  88.                         secureRandom.setSeed(password.getBytes());   
  89.                         kgen.init(128, secureRandom);
  90.                         //kgen.init(128, new SecureRandom(password.getBytes()));   
  91.                         SecretKey secretKey = kgen.generateKey();   
  92.                         byte[] enCodeFormat = secretKey.getEncoded();   
  93.                         SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");   
  94.                         Cipher cipher = Cipher.getInstance("AES");// 创建密码器   
  95.                         byte[] byteContent = content.getBytes("utf-8");   
  96.                         cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化   
  97.                         byte[] result = cipher.doFinal(byteContent);   
  98.                         return result; // 加密   
  99.                 } catch (NoSuchAlgorithmException e) {   
  100.                         e.printStackTrace();   
  101.                 } catch (NoSuchPaddingException e) {   
  102.                         e.printStackTrace();   
  103.                 } catch (InvalidKeyException e) {   
  104.                         e.printStackTrace();   
  105.                 } catch (UnsupportedEncodingException e) {   
  106.                         e.printStackTrace();   
  107.                 } catch (IllegalBlockSizeException e) {   
  108.                         e.printStackTrace();   
  109.                 } catch (BadPaddingException e) {   
  110.                         e.printStackTrace();   
  111.                 }   
  112.                 return null;   
  113.         }  


  114.         /**解密  
  115.          * @param content  待解密内容  
  116.          * @param password 解密密钥  
  117.          * @return  
  118.          */  
  119.         private static byte[] decrypt(byte[] content, String password) {   
  120.                 try {   
  121.                          KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
  122.                        //防止linux下 随机生成key
  123.                              SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );   
  124.                              secureRandom.setSeed(password.getBytes());   
  125.                              kgen.init(128, secureRandom);
  126.                          //kgen.init(128, new SecureRandom(password.getBytes()));   
  127.                          SecretKey secretKey = kgen.generateKey();   
  128.                          byte[] enCodeFormat = secretKey.getEncoded();   
  129.                          SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");               
  130.                          Cipher cipher = Cipher.getInstance("AES");// 创建密码器   
  131.                         cipher.init(Cipher.DECRYPT_MODE, key);// 初始化   
  132.                         byte[] result = cipher.doFinal(content);   
  133.                         return result; // 加密   
  134.                 } catch (NoSuchAlgorithmException e) {   
  135.                         e.printStackTrace();   
  136.                 } catch (NoSuchPaddingException e) {   
  137.                         e.printStackTrace();   
  138.                 } catch (InvalidKeyException e) {   
  139.                         e.printStackTrace();   
  140.                 } catch (IllegalBlockSizeException e) {   
  141.                         e.printStackTrace();   
  142.                 } catch (BadPaddingException e) {   
  143.                         e.printStackTrace();   
  144.                 }   
  145.                 return null;   
  146.         }  

  147.         /**将二进制转换成16进制  
  148.          * @param buf  
  149.          * @return  
  150.          */  
  151.         public static String parseByte2HexStr(byte buf[]) {   
  152.                 StringBuffer sb = new StringBuffer();   
  153.                 for (int i = 0; i < buf.length; i++) {   
  154.                         String hex = Integer.toHexString(buf[i] & 0xFF);   
  155.                         if (hex.length() == 1) {   
  156.                                 hex = '0' + hex;   
  157.                         }   
  158.                         sb.append(hex.toUpperCase());   
  159.                 }   
  160.                 return sb.toString();   
  161.         }  


  162.         /**将16进制转换为二进制  
  163.          * @param hexStr  
  164.          * @return  
  165.          */  
  166.         public static byte[] parseHexStr2Byte(String hexStr) {   
  167.                 if (hexStr.length() < 1)   
  168.                         return null;   
  169.                 byte[] result = new byte[hexStr.length()/2];   
  170.                 for (int i = 0;i< hexStr.length()/2; i++) {   
  171.                         int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);   
  172.                         int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);   
  173.                         result[i] = (byte) (high * 16 + low);   
  174.                 }   
  175.                 return result;   
  176.         }  


  177.         
  178. }
复制代码



改为如下代码




以上在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); 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值