JAVA AES加密与解密

7,937 阅读25分钟
原文链接: blog.csdn.net

一、AES加密简介


AES加密算法是密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。


AES 是一个新的可以用于保护电子数据的加密算法。明确地说,AES 是一个迭代的、对称密钥分组的密码,它可以使用128、192 和 256 位密钥,并且用 128 位(16字节)分组加密和解密数据。与公共密钥密码使用密钥对不同,对称密钥密码使用相同的密钥加密和解密数据。通过分组密码返回的加密数据 的位数与输入数据相同。迭代加密使用一个循环结构,在该循环中重复置换(permutations )和替换(substitutions)输入数据。


AES加密有很多轮的重复和变换。大致步骤如下:


1、密钥扩展(KeyExpansion)。
2、初始轮(Initial Round)。
3、重复轮(Rounds),每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey。
4、最终轮(Final Round),最终轮没有MixColumns。


二、AES在JAVA中的使用


JCE,Java Cryptography Extension,在早期JDK版本中,由于受美国的密码出口条例约束,Java中涉及加解密功能的API被限制出口,所以Java中安全组件被分成了两部分: 不含加密功能的JCA(Java Cryptography Architecture )和含加密功能的JCE(Java Cryptography Extension)。

JCA和JCE的API体系架构

JCE的API都在javax.crypto包下,核心功能包括:加解密、密钥生成(对称)、MAC生成、密钥协商。


(1). 加解密

加解密功能由Cipher组件提供,其也是JCE中最核心的组件。

1. Cipher的几个知识点:

a. Cipher在使用时需以参数方式指定transformation
b. transformation的格式为algorithm/mode/padding,其中algorithm为必输项,如: AES/DES/CBC/PKCS5Padding
c. 缺省的mode为ECB,缺省的padding为PKCS5Padding
d. 在block算法与流加密模式组合时, 需在mode后面指定每次处理的bit数, 如DES/CFB8/NoPadding, 如未指定则使用缺省值, SunJCE缺省值为64bits
e. Cipher有4种操作模式: ENCRYPT_MODE(加密), DECRYPT_MODE(解密), WRAP_MODE(导出Key), UNWRAP_MODE(导入Key),初始化时需指定某种操作模式


[html] view plain copy print?
  1. 算法/模式/填充                 16字节加密后数据长度       不满16字节加密后长度  
  2. AES/CBC/NoPadding                   16                          不支持  
  3. AES/CBC/PKCS5Padding                32                          16  
  4. AES/CBC/ISO10126Padding             32                          16  
  5. AES/CFB/NoPadding                   16                          原始数据长度  
  6. AES/CFB/PKCS5Padding                32                          16  
  7. AES/CFB/ISO10126Padding             32                          16  
  8. AES/ECB/NoPadding                   16                          不支持  
  9. AES/ECB/PKCS5Padding                32                          16  
  10. AES/ECB/ISO10126Padding             32                          16  
  11. AES/OFB/NoPadding                   16                          原始数据长度  
  12. AES/OFB/PKCS5Padding                32                          16  
  13. AES/OFB/ISO10126Padding             32                          16  
  14. AES/PCBC/NoPadding                  16                          不支持  
  15. AES/PCBC/PKCS5Padding               32                          16  
  16. AES/PCBC/ISO10126Padding            32                          16  
算法/模式/填充                 16字节加密后数据长度       不满16字节加密后长度
AES/CBC/NoPadding                   16                          不支持
AES/CBC/PKCS5Padding                32                          16
AES/CBC/ISO10126Padding             32                          16
AES/CFB/NoPadding                   16                          原始数据长度
AES/CFB/PKCS5Padding                32                          16
AES/CFB/ISO10126Padding             32                          16
AES/ECB/NoPadding                   16                          不支持
AES/ECB/PKCS5Padding                32                          16
AES/ECB/ISO10126Padding             32                          16
AES/OFB/NoPadding                   16                          原始数据长度
AES/OFB/PKCS5Padding                32                          16
AES/OFB/ISO10126Padding             32                          16
AES/PCBC/NoPadding                  16                          不支持
AES/PCBC/PKCS5Padding               32                          16
AES/PCBC/ISO10126Padding            32                          16

可以看到,在原始数据长度为16的整数倍时,假如原始数据长度等于16*n,则使用NoPadding时加密后数据长度等于16*n,其它情况下加密数据长 度等于16*(n+1)。在不足16的整数倍的情况下,假如原始数据长度等于16*n+m[其中m小于16],除了NoPadding填充之外的任何方 式,加密数据长度都等于16*(n+1);NoPadding填充情况下,CBC、ECB和PCBC三种模式是不支持的,CFB、OFB两种模式下则加密 数据长度等于原始数据长度。


2. 对称加密的算法与密钥长度选择


算法名称 密钥长 块长 速度 说明
DES 56 64 64 不安全, 不要使用
3DES 112/168 64 很慢 中等安全, 适合加密较小的数据
AES 128, 192, 256 128 安全
Blowfish (4至56)*8 64 快 应该安全, 在安全界尚未被充分分析、论证
RC4 40-1024 64 很快 安全性不明确


推荐使用AES算法。一般认为128bits的密钥已足够安全,如果可以请选择256bits的密钥。注意:


a. 密钥长度是在生成密钥时指定的,如:

[html] view plain copy print?
  1. KeyGenerator generator = KeyGenerator.getInstance("AES/CBC/PKCS5PADDING");  
  2. generator.init(256);  
  3. SecretKey key = generator.generateKey();  
KeyGenerator generator = KeyGenerator.getInstance("AES/CBC/PKCS5PADDING");
generator.init(256);
SecretKey key = generator.generateKey();

3. 加密示例代码 [html] view plain copy print?
  1. /**  
  2.   * 根据密钥对指定的明文plainText进行加密.  
  3.   *  
  4.   * @param plainText 明文  
  5.   * @return 加密后的密文.  
  6.   */  
  7.  public static final String encrypt(String plainText) {  
  8.     Key secretKey = getKey("fendo888");  
  9.     try {  
  10.         Cipher cipher = Cipher.getInstance("AES");  
  11.         cipher.init(Cipher.ENCRYPT_MODE, secretKey);  
  12.         byte[] p = plainText.getBytes("UTF-8");  
  13.         byte[] result = cipher.doFinal(p);  
  14.         BASE64Encoder encoder = new BASE64Encoder();  
  15.         String encoded = encoder.encode(result);  
  16.         return encoded;  
  17.     } catch (Exception e) {  
  18.         throw new RuntimeException(e);  
  19.     }   
  20.  }  
   /**
     * 根据密钥对指定的明文plainText进行加密.
     *
     * @param plainText 明文
     * @return 加密后的密文.
     */
    public static final String encrypt(String plainText) {
    	Key secretKey = getKey("fendo888");
    	try {
    		Cipher cipher = Cipher.getInstance("AES");
    		cipher.init(Cipher.ENCRYPT_MODE, secretKey);
    		byte[] p = plainText.getBytes("UTF-8");
    		byte[] result = cipher.doFinal(p);
    		BASE64Encoder encoder = new BASE64Encoder();
    		String encoded = encoder.encode(result);
    		return encoded;
    	} catch (Exception e) {
    		throw new RuntimeException(e);
    	} 
    }

4. 解密示例代码

[html] view plain copy print?
  1. /**  
  2.  * 根据密钥对指定的密文cipherText进行解密.  
  3.  *  
  4.  * @param cipherText 密文  
  5.  * @return 解密后的明文.  
  6.  */  
  7. public static final String decrypt(String cipherText) {  
  8.     Key secretKey = getKey("fendo888");  
  9.     try {  
  10.         Cipher cipher = Cipher.getInstance("AES");  
  11.         cipher.init(Cipher.DECRYPT_MODE, secretKey);  
  12.         BASE64Decoder decoder = new BASE64Decoder();  
  13.         byte[] c = decoder.decodeBuffer(cipherText);  
  14.         byte[] result = cipher.doFinal(c);  
  15.         String plainText = new String(result, "UTF-8");  
  16.         return plainText;  
  17.     } catch (Exception e) {  
  18.         throw new RuntimeException(e);  
  19.     }  
  20. }  
    /**
     * 根据密钥对指定的密文cipherText进行解密.
     *
     * @param cipherText 密文
     * @return 解密后的明文.
     */
    public static final String decrypt(String cipherText) {
    	Key secretKey = getKey("fendo888");
    	try {
    		Cipher cipher = Cipher.getInstance("AES");
    		cipher.init(Cipher.DECRYPT_MODE, secretKey);
    		BASE64Decoder decoder = new BASE64Decoder();
    		byte[] c = decoder.decodeBuffer(cipherText);
    		byte[] result = cipher.doFinal(c);
    		String plainText = new String(result, "UTF-8");
    		return plainText;
    	} catch (Exception e) {
    		throw new RuntimeException(e);
    	}
    }

其中的getKey()

[html] view plain copy print?
  1. public static Key getKey(String keySeed) {    
  2.         if (keySeed == null) {    
  3.             keySeed = System.getenv("AES_SYS_KEY");    
  4.         }    
  5.         if (keySeed == null) {    
  6.             keySeed = System.getProperty("AES_SYS_KEY");    
  7.         }    
  8.         if (keySeed == null || keySeed.trim().length() == 0) {    
  9.             keySeed = "abcd1234!@#$";// 默认种子    
  10.         }    
  11.         try {    
  12.             SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");    
  13.             secureRandom.setSeed(keySeed.getBytes());    
  14.             KeyGenerator generator = KeyGenerator.getInstance("AES");    
  15.             generator.init(secureRandom);    
  16.             return generator.generateKey();    
  17.         } catch (Exception e) {    
  18.             throw new RuntimeException(e);    
  19.         }    
  20. }  
public static Key getKey(String keySeed) {  
        if (keySeed == null) {  
            keySeed = System.getenv("AES_SYS_KEY");  
        }  
        if (keySeed == null) {  
            keySeed = System.getProperty("AES_SYS_KEY");  
        }  
        if (keySeed == null || keySeed.trim().length() == 0) {  
            keySeed = "abcd1234!@#$";// 默认种子  
        }  
        try {  
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");  
            secureRandom.setSeed(keySeed.getBytes());  
            KeyGenerator generator = KeyGenerator.getInstance("AES");  
            generator.init(secureRandom);  
            return generator.generateKey();  
        } catch (Exception e) {  
            throw new RuntimeException(e);  
        }  
}


三.AESUtils帮助类

[html] view plain copyprint?
  1. package com.fendo.MD5;  
  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 org.apache.commons.lang3.StringUtils;  
  18.   
  19. import sun.misc.BASE64Decoder;  
  20. import sun.misc.BASE64Encoder;  
  21.   
  22. /**     
  23.  * @Title: AESUtils.java   
  24.  * @Package com.fendo.MD5   
  25.  * @Description: TODO  
  26.  * @author fendo  
  27.  * @date 2017年9月11日 下午5:48:17   
  28.  * @version V1.0     
  29. */  
  30. public class AESUtils {  
  31.   
  32.       
  33.     private static final String encodeRules = "fendo";  
  34.   
  35.     /**  
  36.      * 加密  
  37.      * 1.构造密钥生成器  
  38.      * 2.根据ecnodeRules规则初始化密钥生成器  
  39.      * 3.产生密钥  
  40.      * 4.创建和初始化密码器  
  41.      * 5.内容加密  
  42.      * 6.返回字符串  
  43.      */  
  44.     public static String AESEncode(String content) {  
  45.         try {  
  46.             //1.构造密钥生成器,指定为AES算法,不区分大小写  
  47.             KeyGenerator keygen = KeyGenerator.getInstance("AES");  
  48.             //2.根据ecnodeRules规则初始化密钥生成器  
  49.             //生成一个128位的随机源,根据传入的字节数组  
  50.             SecureRandom random = SecureRandom.getInstance("SHA1PRNG");  
  51.             random.setSeed(encodeRules.getBytes());  
  52.             keygen.init(128, random);  
  53.             //3.产生原始对称密钥  
  54.             SecretKey original_key = keygen.generateKey();  
  55.             //4.获得原始对称密钥的字节数组  
  56.             byte[] raw = original_key.getEncoded();  
  57.             //5.根据字节数组生成AES密钥  
  58.             SecretKey key = new SecretKeySpec(raw, "AES");  
  59.             //6.根据指定算法AES自成密码器  
  60.             Cipher cipher = Cipher.getInstance("AES");  
  61.             //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY  
  62.             cipher.init(Cipher.ENCRYPT_MODE, key);  
  63.             //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码  
  64.             byte[] byte_encode = content.getBytes("utf-8");  
  65.             //9.根据密码器的初始化方式--加密:将数据加密  
  66.             byte[] byte_AES = cipher.doFinal(byte_encode);  
  67.             //10.将加密后的数据转换为字符串  
  68.             //这里用Base64Encoder中会找不到包  
  69.             //解决办法:  
  70.             //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。  
  71.             String AES_encode = new String(new BASE64Encoder().encode(byte_AES));  
  72.             //11.将字符串返回  
  73.             return AES_encode;  
  74.         } catch (NoSuchAlgorithmException e) {  
  75.             e.printStackTrace();  
  76.         } catch (NoSuchPaddingException e) {  
  77.             e.printStackTrace();  
  78.         } catch (InvalidKeyException e) {  
  79.             e.printStackTrace();  
  80.         } catch (IllegalBlockSizeException e) {  
  81.             e.printStackTrace();  
  82.         } catch (BadPaddingException e) {  
  83.             e.printStackTrace();  
  84.         } catch (UnsupportedEncodingException e) {  
  85.             e.printStackTrace();  
  86.         }  
  87.         //如果有错就返加nulll  
  88.         return null;  
  89.     }  
  90.   
  91.       
  92.   
  93.     /**   
  94.      * AES加密   
  95.      * @param content 待加密的内容   
  96.      * @param encryptKey 加密密钥   
  97.      * @return 加密后的byte[]   
  98.      * @throws Exception   
  99.      */    
  100.     public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {    
  101.         KeyGenerator kgen = KeyGenerator.getInstance("AES");    
  102.         kgen.init(128, new SecureRandom(encryptKey.getBytes()));    
  103.     
  104.         Cipher cipher = Cipher.getInstance("AES");    
  105.         cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));    
  106.             
  107.         return cipher.doFinal(content.getBytes("utf-8"));    
  108.     }    
  109.       
  110.     /**  
  111.      * 解密  
  112.      * 解密过程:  
  113.      * 1.同加密1-4步  
  114.      * 2.将加密后的字符串反纺成byte[]数组  
  115.      * 3.将加密内容解密  
  116.      */  
  117.     public static String AESDecode(String content) {  
  118.         try {  
  119.             //1.构造密钥生成器,指定为AES算法,不区分大小写  
  120.             KeyGenerator keygen = KeyGenerator.getInstance("AES");  
  121.             //2.根据ecnodeRules规则初始化密钥生成器  
  122.             //生成一个128位的随机源,根据传入的字节数组  
  123.             SecureRandom random = SecureRandom.getInstance("SHA1PRNG");  
  124.             random.setSeed(encodeRules.getBytes());  
  125.             keygen.init(128, random);  
  126.             //3.产生原始对称密钥  
  127.             SecretKey original_key = keygen.generateKey();  
  128.             //4.获得原始对称密钥的字节数组  
  129.             byte[] raw = original_key.getEncoded();  
  130.             //5.根据字节数组生成AES密钥  
  131.             SecretKey key = new SecretKeySpec(raw, "AES");  
  132.             //6.根据指定算法AES自成密码器  
  133.             Cipher cipher = Cipher.getInstance("AES");  
  134.             //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY  
  135.             cipher.init(Cipher.DECRYPT_MODE, key);  
  136.             //8.将加密并编码后的内容解码成字节数组  
  137.             byte[] byte_content = new BASE64Decoder().decodeBuffer(content);  
  138.             /*  
  139.              * 解密  
  140.              */  
  141.             byte[] byte_decode = cipher.doFinal(byte_content);  
  142.             String AES_decode = new String(byte_decode, "utf-8");  
  143.             return AES_decode;  
  144.         } catch (NoSuchAlgorithmException e) {  
  145.             e.printStackTrace();  
  146.         } catch (NoSuchPaddingException e) {  
  147.             e.printStackTrace();  
  148.         } catch (InvalidKeyException e) {  
  149.             e.printStackTrace();  
  150.         } catch (IOException e) {  
  151.             e.printStackTrace();  
  152.         } catch (IllegalBlockSizeException e) {  
  153.             e.printStackTrace();  
  154.         } catch (BadPaddingException e) {  
  155.             e.printStackTrace();  
  156.         }  
  157.         //如果有错就返加nulll  
  158.         return null;  
  159.     }  
  160.       
  161.       
  162.     /**   
  163.      * AES解密   
  164.      * @param encryptBytes 待解密的byte[]   
  165.      * @param decryptKey 解密密钥   
  166.      * @return 解密后的String   
  167.      * @throws Exception   
  168.      */    
  169.     public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {    
  170.         KeyGenerator kgen = KeyGenerator.getInstance("AES");    
  171.         kgen.init(128, new SecureRandom(decryptKey.getBytes()));    
  172.             
  173.         Cipher cipher = Cipher.getInstance("AES");    
  174.         cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));    
  175.         byte[] decryptBytes = cipher.doFinal(encryptBytes);    
  176.             
  177.         return new String(decryptBytes);    
  178.     }    
  179.       
  180.     /**   
  181.      * base 64 加密   
  182.      * @param bytes 待编码的byte[]   
  183.      * @return 编码后的base 64 code   
  184.      */    
  185.     public static String base64Encode(byte[] bytes){    
  186.         return new BASE64Encoder().encode(bytes);    
  187.     }    
  188.       
  189.     /**   
  190.      * base 64 解密   
  191.      * @param base64Code 待解码的base 64 code   
  192.      * @return 解码后的byte[]   
  193.      * @throws Exception   
  194.      */    
  195.     public static byte[] base64Decode(String base64Code) throws Exception{    
  196.         return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);    
  197.     }    
  198.       
  199.     /**   
  200.      * 将base 64 code AES解密   
  201.      * @param encryptStr 待解密的base 64 code   
  202.      * @param decryptKey 解密密钥   
  203.      * @return 解密后的string   
  204.      * @throws Exception   
  205.      */    
  206.     public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {    
  207.         return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);    
  208.     }    
  209.       
  210.     /**   
  211.      * AES加密为base 64 code   
  212.      * @param content 待加密的内容   
  213.      * @param encryptKey 加密密钥   
  214.      * @return 加密后的base 64 code   
  215.      * @throws Exception   
  216.      */    
  217.     public static String aesEncrypt(String content, String encryptKey) throws Exception {    
  218.         return base64Encode(aesEncryptToBytes(content, encryptKey));    
  219.     }  
  220.   
  221.     public static void main(String[] args) {  
  222.         String[] keys = {  
  223.                 "", "root"  
  224.         };  
  225.         System.out.println("key | AESEncode | AESDecode");  
  226.         for (String key : keys) {  
  227.             System.out.print("key:"+key + " | ");  
  228.             String encryptString = AESEncode(key);  
  229.             System.out.print(encryptString + " | ");  
  230.             String decryptString = AESDecode(encryptString);  
  231.             System.out.println(decryptString);  
  232.         }  
  233.     }  
  234. }  
package com.fendo.MD5;

import java.io.IOException;
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;

import org.apache.commons.lang3.StringUtils;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**   
 * @Title: AESUtils.java 
 * @Package com.fendo.MD5 
 * @Description: TODO
 * @author fendo
 * @date 2017年9月11日 下午5:48:17 
 * @version V1.0   
*/
public class AESUtils {

	
    private static final String encodeRules = "fendo";

    /**
     * 加密
     * 1.构造密钥生成器
     * 2.根据ecnodeRules规则初始化密钥生成器
     * 3.产生密钥
     * 4.创建和初始化密码器
     * 5.内容加密
     * 6.返回字符串
     */
    public static String AESEncode(String content) {
        try {
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(encodeRules.getBytes());
            keygen.init(128, random);
            //3.产生原始对称密钥
            SecretKey original_key = keygen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte[] raw = original_key.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKey key = new SecretKeySpec(raw, "AES");
            //6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance("AES");
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.ENCRYPT_MODE, key);
            //8.获取加密内容的字节数组(这里要设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte[] byte_encode = content.getBytes("utf-8");
            //9.根据密码器的初始化方式--加密:将数据加密
            byte[] byte_AES = cipher.doFinal(byte_encode);
            //10.将加密后的数据转换为字符串
            //这里用Base64Encoder中会找不到包
            //解决办法:
            //在项目的Build path中先移除JRE System Library,再添加库JRE System Library,重新编译后就一切正常了。
            String AES_encode = new String(new BASE64Encoder().encode(byte_AES));
            //11.将字符串返回
            return AES_encode;
        } 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();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        //如果有错就返加nulll
        return null;
    }

    

    /** 
     * AES加密 
     * @param content 待加密的内容 
     * @param encryptKey 加密密钥 
     * @return 加密后的byte[] 
     * @throws Exception 
     */  
    public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception {  
        KeyGenerator kgen = KeyGenerator.getInstance("AES");  
        kgen.init(128, new SecureRandom(encryptKey.getBytes()));  
  
        Cipher cipher = Cipher.getInstance("AES");  
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));  
          
        return cipher.doFinal(content.getBytes("utf-8"));  
    }  
    
    /**
     * 解密
     * 解密过程:
     * 1.同加密1-4步
     * 2.将加密后的字符串反纺成byte[]数组
     * 3.将加密内容解密
     */
    public static String AESDecode(String content) {
        try {
            //1.构造密钥生成器,指定为AES算法,不区分大小写
            KeyGenerator keygen = KeyGenerator.getInstance("AES");
            //2.根据ecnodeRules规则初始化密钥生成器
            //生成一个128位的随机源,根据传入的字节数组
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(encodeRules.getBytes());
            keygen.init(128, random);
            //3.产生原始对称密钥
            SecretKey original_key = keygen.generateKey();
            //4.获得原始对称密钥的字节数组
            byte[] raw = original_key.getEncoded();
            //5.根据字节数组生成AES密钥
            SecretKey key = new SecretKeySpec(raw, "AES");
            //6.根据指定算法AES自成密码器
            Cipher cipher = Cipher.getInstance("AES");
            //7.初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY
            cipher.init(Cipher.DECRYPT_MODE, key);
            //8.将加密并编码后的内容解码成字节数组
            byte[] byte_content = new BASE64Decoder().decodeBuffer(content);
            /*
             * 解密
             */
            byte[] byte_decode = cipher.doFinal(byte_content);
            String AES_decode = new String(byte_decode, "utf-8");
            return AES_decode;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        }
        //如果有错就返加nulll
        return null;
    }
    
    
    /** 
     * AES解密 
     * @param encryptBytes 待解密的byte[] 
     * @param decryptKey 解密密钥 
     * @return 解密后的String 
     * @throws Exception 
     */  
    public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception {  
        KeyGenerator kgen = KeyGenerator.getInstance("AES");  
        kgen.init(128, new SecureRandom(decryptKey.getBytes()));  
          
        Cipher cipher = Cipher.getInstance("AES");  
        cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(kgen.generateKey().getEncoded(), "AES"));  
        byte[] decryptBytes = cipher.doFinal(encryptBytes);  
          
        return new String(decryptBytes);  
    }  
    
    /** 
     * base 64 加密 
     * @param bytes 待编码的byte[] 
     * @return 编码后的base 64 code 
     */  
    public static String base64Encode(byte[] bytes){  
        return new BASE64Encoder().encode(bytes);  
    }  
    
    /** 
     * base 64 解密 
     * @param base64Code 待解码的base 64 code 
     * @return 解码后的byte[] 
     * @throws Exception 
     */  
    public static byte[] base64Decode(String base64Code) throws Exception{  
        return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);  
    }  
    
    /** 
     * 将base 64 code AES解密 
     * @param encryptStr 待解密的base 64 code 
     * @param decryptKey 解密密钥 
     * @return 解密后的string 
     * @throws Exception 
     */  
    public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception {  
        return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey);  
    }  
    
    /** 
     * AES加密为base 64 code 
     * @param content 待加密的内容 
     * @param encryptKey 加密密钥 
     * @return 加密后的base 64 code 
     * @throws Exception 
     */  
    public static String aesEncrypt(String content, String encryptKey) throws Exception {  
        return base64Encode(aesEncryptToBytes(content, encryptKey));  
    }

    public static void main(String[] args) {
        String[] keys = {
                "", "root"
        };
        System.out.println("key | AESEncode | AESDecode");
        for (String key : keys) {
            System.out.print("key:"+key + " | ");
            String encryptString = AESEncode(key);
            System.out.print(encryptString + " | ");
            String decryptString = AESDecode(encryptString);
            System.out.println(decryptString);
        }
    }
}