AES加密跨平台出现的问题

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的方法上,如下:

viw plaincopy to clipboardprint?

  1. public static SecretKey getKey (String strKey) {  

  2.          try {           

  3.             KeyGenerator _generator = KeyGenerator.getInstance( "AES" );  

  4.             _generator.init(128new SecureRandom(strKey.getBytes()));  

  5.                 return _generator.generateKey();  

  6.         }  catch (Exception e) {  

  7.              throw new RuntimeException( " 初始化密钥出现异常 " );  

  8.         }  

  9.       }   

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

view plaincopy to clipboardprint?

  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 系统上则不同。

一般情况下

package util;

import java.io.UnsupportedEncodingException;

import java.security.InvalidKeyException;

import java.security.NoSuchAlgorithmException;

import java.security.SecureRandom;

import javax.crypto.BadPaddingException;

import javax.crypto.Cipher;

import javax.crypto.IllegalBlockSizeException;

import javax.crypto.KeyGenerator;

import javax.crypto.NoSuchPaddingException;

import javax.crypto.SecretKey;

import javax.crypto.spec.SecretKeySpec;

public class AESUtil {

/**

    * 加密

    * 

    * @param content 需要加密的内容

    * @param password  加密密码

    * @return

    */

   public static byte[] encrypt(String content, String password) {

           try {           

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

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

                   

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

                   secureRandom.setSeed(password.getBytes());  

                   kgen.init(128,secureRandom);

               

                   

                   

                   SecretKey secretKey = kgen.generateKey();

                   byte[] enCodeFormat = secretKey.getEncoded();

                   SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");

                   Cipher cipher = Cipher.getInstance("AES");// 创建密码器

                   byte[] byteContent = content.getBytes("utf-8");

                   cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化

                   byte[] result = cipher.doFinal(byteContent);

                   return result; // 加密

           } catch (NoSuchAlgorithmException e) {

                   e.printStackTrace();

           } catch (NoSuchPaddingException e) {

                   e.printStackTrace();

           } catch (InvalidKeyException e) {

                   e.printStackTrace();

           } catch (UnsupportedEncodingException e) {

                   e.printStackTrace();

           } catch (IllegalBlockSizeException e) {

                   e.printStackTrace();

           } catch (BadPaddingException e) {

                   e.printStackTrace();

           }

           return null;

   }

   

   

   

   /**解密

    * @param content  待解密内容

    * @param password 解密密钥

    * @return

    */

   public static byte[] decrypt(byte[] content, String password) {

           try {

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

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

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

                    secureRandom.setSeed(password.getBytes());  

                    kgen.init(128,secureRandom); 

                    

                    

                    

                    

                    SecretKey secretKey = kgen.generateKey();

                    byte[] enCodeFormat = secretKey.getEncoded();

                    SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");            

                    Cipher cipher = Cipher.getInstance("AES");// 创建密码器

                   cipher.init(Cipher.DECRYPT_MODE, key);// 初始化

                   byte[] result = cipher.doFinal(content);

                   return result; // 加密

           } catch (NoSuchAlgorithmException e) {

                   e.printStackTrace();

           } catch (NoSuchPaddingException e) {

                   e.printStackTrace();

           } catch (InvalidKeyException e) {

                   e.printStackTrace();

           } catch (IllegalBlockSizeException e) {

                   e.printStackTrace();

           } catch (BadPaddingException e) {

                   e.printStackTrace();

           }

           return null;

   }

   

   

   

   /**将二进制转换成16进制

    * @param buf

    * @return

    */

   public static String parseByte2HexStr(byte buf[]) {

           StringBuffer sb = new StringBuffer();

           for (int i = 0; i < buf.length; i++) {

                   String hex = Integer.toHexString(buf[i] & 0xFF);

                   if (hex.length() == 1) {

                           hex = '0' + hex;

                   }

                   sb.append(hex.toUpperCase());

           }

           return sb.toString();

   }

   

   /**将16进制转换为二进制

    * @param hexStr

    * @return

    */

   public static byte[] parseHexStr2Byte(String hexStr) {

           if (hexStr.length() < 1)

                   return null;

           byte[] result = new byte[hexStr.length()/2];

           for (int i = 0;i< hexStr.length()/2; i++) {

                   int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);

                   int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);

                   result[i] = (byte) (high * 16 + low);

           }

           return result;

   }   

}

原文地址:https://www.cnblogs.com/wzyxidian/p/4383363.html