赵计刚
每天进步一点点

注意:本节内容主要参考自《Java加密与解密的艺术(第2版)》第7章“初等加密算法--对称加密算法”

8.1、AES

特点:

  • 密钥建立时间短、灵敏性好、内存需求低(不管怎样,反正就是好)
  • 最常用的对称加密算法

8.2、实现方式

  • JDK(密钥长度有128,192,256三种选法,提供PKCS5Padding的填充模式)
  • Bouncy Castle(密钥长度有128,192,256三种选法,提供PKCS7Padding的填充模式)

8.2.1、基于JDK或BC的AES实现(工作模式为ECB)

  1 package com.util.aes;
  2 
  3 import java.io.UnsupportedEncodingException;
  4 import java.security.InvalidAlgorithmParameterException;
  5 import java.security.InvalidKeyException;
  6 import java.security.Key;
  7 import java.security.NoSuchAlgorithmException;
  8 import java.security.NoSuchProviderException;
  9 import java.security.Security;
 10 import java.security.spec.InvalidKeySpecException;
 11 
 12 import javax.crypto.BadPaddingException;
 13 import javax.crypto.Cipher;
 14 import javax.crypto.IllegalBlockSizeException;
 15 import javax.crypto.KeyGenerator;
 16 import javax.crypto.NoSuchPaddingException;
 17 import javax.crypto.SecretKey;
 18 import javax.crypto.spec.SecretKeySpec;
 19 
 20 import org.apache.commons.codec.binary.Base64;
 21 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 22 
 23 /**
 24  * 基于JDK或BC的AES算法,工作模式采用ECB
 25  */
 26 public class AESJDK {
 27     private static final String ENCODING = "UTF-8";
 28     private static final String KEY_ALGORITHM = "AES";//产生密钥的算法
 29     private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//加解密算法 格式:算法/工作模式/填充模式 注意:ECB不使用IV参数
 30     /**
 31      * 产生密钥
 32      */
 33     public static byte[] getKey() throws NoSuchAlgorithmException{
 34         Security.addProvider(new BouncyCastleProvider());//在BC中用,JDK下去除
 35         KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
 36         keyGenerator.init(256);//初始化密钥长度,128,192,256(选用192和256的时候需要配置无政策限制权限文件--JDK6)
 37         SecretKey key =keyGenerator.generateKey();//产生密钥
 38         return key.getEncoded();
 39     }
 40     
 41     /**
 42      * 还原密钥:二进制字节数组转换为Java对象
 43      */
 44     public static Key toKey(byte[] keyByte){
 45         return new SecretKeySpec(keyByte, KEY_ALGORITHM);
 46     }
 47     
 48     /**
 49      * AES加密
 50      * @param data     带加密数据
 51      * @param keyByte  密钥
 52      */
 53     public static byte[] encrypt(String data, byte[] keyByte) throws InvalidKeyException, 
 54                                                                      NoSuchAlgorithmException, 
 55                                                                      InvalidKeySpecException, 
 56                                                                      NoSuchPaddingException, 
 57                                                                      IllegalBlockSizeException, 
 58                                                                      BadPaddingException, 
 59                                                                      UnsupportedEncodingException, 
 60                                                                      NoSuchProviderException, 
 61                                                                      InvalidAlgorithmParameterException{
 62         Key key = toKey(keyByte);//还原密钥
 63         //Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//JDK下用
 64         Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
 65         cipher.init(Cipher.ENCRYPT_MODE, key);//设置加密模式并且初始化key
 66         return cipher.doFinal(data.getBytes(ENCODING));
 67     }
 68     
 69     /**
 70      * AES加密,并转为16进制字符串或Base64编码字符串
 71      */
 72     public static String encryptAESHex(String data, byte[] keyByte) throws InvalidKeyException, 
 73                                                                            NoSuchAlgorithmException, 
 74                                                                            InvalidKeySpecException, 
 75                                                                            NoSuchPaddingException, 
 76                                                                            IllegalBlockSizeException, 
 77                                                                            BadPaddingException, 
 78                                                                            UnsupportedEncodingException, 
 79                                                                            NoSuchProviderException, 
 80                                                                            InvalidAlgorithmParameterException {
 81         byte[] encodedByte = encrypt(data, keyByte);
 82         //return new String(Hex.encode(encodedByte));//借助BC
 83         //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
 84         return Base64.encodeBase64String(encodedByte);//借助CC的Base64编码
 85     }
 86     
 87     /**
 88      * AES解密
 89      * @param data        待解密数据为字节数组
 90      * @param keyByte    密钥
 91      */
 92     public static byte[] decrypt(byte[] data, byte[] keyByte) throws InvalidKeyException, 
 93                                                                      NoSuchAlgorithmException, 
 94                                                                      InvalidKeySpecException, 
 95                                                                      NoSuchPaddingException, 
 96                                                                      IllegalBlockSizeException, 
 97                                                                      BadPaddingException, 
 98                                                                      UnsupportedEncodingException, 
 99                                                                      NoSuchProviderException, 
100                                                                      InvalidAlgorithmParameterException {
101         Key key = toKey(keyByte);//还原密钥
102         Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
103         //Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//JDK下用
104         cipher.init(Cipher.DECRYPT_MODE, key);
105         return cipher.doFinal(data);
106     }
107     
108     /**
109      * AES解密
110      * @param data        待解密数据为字符串
111      * @param keyByte    密钥
112      */
113     public static byte[] decrypt(String data, byte[] keyByte) throws InvalidKeyException, 
114                                                                      NoSuchAlgorithmException, 
115                                                                      InvalidKeySpecException, 
116                                                                      NoSuchPaddingException, 
117                                                                      IllegalBlockSizeException, 
118                                                                      BadPaddingException, 
119                                                                      UnsupportedEncodingException, 
120                                                                      NoSuchProviderException, 
121                                                                      InvalidAlgorithmParameterException {
122         Key key = toKey(keyByte);//还原密钥
123         //Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//JDK下用
124         Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
125         cipher.init(Cipher.DECRYPT_MODE, key);
126         return cipher.doFinal(Base64.decodeBase64(data));//注意data不可以直接采用data.getByte()方法转化为字节数组,否则会抛异常
127     }
128     
129     /**
130      * 测试
131      */
132     public static void main(String[] args) throws NoSuchAlgorithmException, 
133                                                   InvalidKeyException, 
134                                                   InvalidKeySpecException, 
135                                                   NoSuchPaddingException, 
136                                                   IllegalBlockSizeException, 
137                                                   BadPaddingException, 
138                                                   UnsupportedEncodingException, 
139                                                   NoSuchProviderException, 
140                                                   InvalidAlgorithmParameterException {
141         String data = "找一个好姑娘做老婆是我的梦 想!";
142         /*************测试encrypt()、decrypt()**************/
143         System.out.println("原文-->"+data);
144         byte[] keyByte = AESJDK.getKey(); 
145         System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
146         byte[] encodedByte = AESJDK.encrypt(data, keyByte);
147         System.out.println("加密后-->"+encodedByte);
148         byte[] encodedByte2 = AESJDK.encrypt(data, keyByte);
149         System.out.println("加密后-->"+encodedByte2);
150         byte[] decodedByte = AESJDK.decrypt(encodedByte, keyByte);
151         System.out.println("解密后-->"+decodedByte);
152         for(int i=0;i<encodedByte.length;i++){
153             System.out.println(encodedByte[i]==encodedByte2[i]);
154         }
155         /*************测试encryptAESHex()、decrypt()**************/
156         System.out.println("原文-->"+data);
157         byte[] keyByte3 = AESJDK.getKey(); 
158         System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
159         String encodedStr = AESJDK.encryptAESHex(data, keyByte3);
160         System.out.println("加密后-->"+encodedStr);
161         String encodedByte4 = AESJDK.encryptAESHex(data, keyByte3);
162         System.out.println("加密后-->"+encodedByte4);
163         byte[] decodedByte3 = AESJDK.decrypt(Base64.decodeBase64(encodedStr), keyByte3);
164         System.out.println("解密Byte[]后-->"+decodedByte3);
165         byte[] decodedByte4 = AESJDK.decrypt(encodedStr, keyByte3);
166         System.out.println("解密String后-->"+decodedByte4);
167     }
168 }
View Code

注意点:

  • 本文JDK版本采用的是1.6(也是当下企业常用的版本)
  • 基于JDK或是基于BC去实现查看代码中注释即可
  • 想使用BC下,需要在生成密钥的地方加上Security.addProvider(new BouncyCastleProvider());(这与书中不同,可能JDK7不需要加)
  • 密钥初始化长度可以为128,192,256,其中在选用192和256的时候需要配置无政策限制权限文件,具体方法文末会讲。(这与书中不同,可能JDK7下192不需要配置那个文件)

这个类具体在实际中使用的方式见"Java企业项目开发实践"《第六章 企业项目开发--cookie》,具体链接如下:

http://www.cnblogs.com/java-zhao/p/5128393.html

8.2.2、基于BC的AES实现(工作模式为CTR)(这个类在我后边的使用中有点问题,以后有时间再来解决,如果要用AES算法的话,用上边那种就好)

  1 package com.util.aes;
  2 
  3 import java.io.UnsupportedEncodingException;
  4 import java.security.InvalidAlgorithmParameterException;
  5 import java.security.InvalidKeyException;
  6 import java.security.Key;
  7 import java.security.NoSuchAlgorithmException;
  8 import java.security.NoSuchProviderException;
  9 import java.security.Security;
 10 import java.security.spec.InvalidKeySpecException;
 11 
 12 import javax.crypto.BadPaddingException;
 13 import javax.crypto.Cipher;
 14 import javax.crypto.IllegalBlockSizeException;
 15 import javax.crypto.KeyGenerator;
 16 import javax.crypto.NoSuchPaddingException;
 17 import javax.crypto.SecretKey;
 18 import javax.crypto.spec.IvParameterSpec;
 19 import javax.crypto.spec.SecretKeySpec;
 20 
 21 import org.apache.commons.codec.binary.Base64;
 22 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 23 
 24 /**
 25  * 基于BC的AES算法,工作模式采用CTR
 26  */
 27 public class AESBC {
 28     private static final String ENCODING = "UTF-8";
 29     private static final String KEY_ALGORITHM = "AES";//产生密钥的算法
 30     private static final String CIPHER_ALGORITHM = "AES/CTR/PKCS7Padding";//加解密算法 格式:算法/工作模式/填充模式 注意:ECB不使用IV参数,CTR使用
 31     private static final byte[] IV = "zhaojigangzhaoji".getBytes();//注意:这里需要是十六个字符,用于CTR
 32     /**
 33      * 产生密钥
 34      */
 35     public static byte[] getKey() throws NoSuchAlgorithmException{
 36         Security.addProvider(new BouncyCastleProvider());//加入BCProvider
 37         KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
 38         keyGenerator.init(256);//初始化密钥长度,128,192,256(选用192和256的时候需要配置无政策限制权限文件--JDK6)
 39         SecretKey key =keyGenerator.generateKey();//产生密钥
 40         return key.getEncoded();
 41     }
 42     
 43     /**
 44      * 还原密钥:二进制字节数组转换为Java对象
 45      */
 46     public static Key toKey(byte[] keyByte){
 47         return new SecretKeySpec(keyByte, KEY_ALGORITHM);
 48     }
 49     
 50     /**
 51      * AES加密
 52      * @param data     带加密数据
 53      * @param keyByte  密钥
 54      */
 55     public static byte[] encrypt(String data, byte[] keyByte) throws InvalidKeyException, 
 56                                                                      NoSuchAlgorithmException, 
 57                                                                      InvalidKeySpecException, 
 58                                                                      NoSuchPaddingException, 
 59                                                                      IllegalBlockSizeException, 
 60                                                                      BadPaddingException, 
 61                                                                      UnsupportedEncodingException, 
 62                                                                      NoSuchProviderException, 
 63                                                                      InvalidAlgorithmParameterException{
 64         Key key = toKey(keyByte);//还原密钥
 65         Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//使用BC
 66         cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));//设置加密模式并且初始化key,加入IV用于BC下的CTR
 67         return cipher.doFinal(data.getBytes(ENCODING));
 68     }
 69     
 70     /**
 71      * AES加密,并转为16进制字符串或Base64编码字符串
 72      */
 73     public static String encryptAESHex(String data, byte[] keyByte) throws InvalidKeyException, 
 74                                                                            NoSuchAlgorithmException, 
 75                                                                            InvalidKeySpecException, 
 76                                                                            NoSuchPaddingException, 
 77                                                                            IllegalBlockSizeException, 
 78                                                                            BadPaddingException, 
 79                                                                            UnsupportedEncodingException, 
 80                                                                            NoSuchProviderException, 
 81                                                                            InvalidAlgorithmParameterException {
 82         byte[] encodedByte = encrypt(data, keyByte);
 83         //return new String(Hex.encode(encodedByte));//借助BC
 84         //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
 85         return Base64.encodeBase64String(encodedByte);//借助CC的Base64编码
 86     }
 87     
 88     /**
 89      * AES解密
 90      * @param data        待解密数据为字节数组
 91      * @param keyByte    密钥
 92      */
 93     public static byte[] decrypt(byte[] data, byte[] keyByte) throws InvalidKeyException, 
 94                                                                      NoSuchAlgorithmException, 
 95                                                                      InvalidKeySpecException, 
 96                                                                      NoSuchPaddingException, 
 97                                                                      IllegalBlockSizeException, 
 98                                                                      BadPaddingException, 
 99                                                                      UnsupportedEncodingException, 
100                                                                      NoSuchProviderException, 
101                                                                      InvalidAlgorithmParameterException {
102         Key key = toKey(keyByte);//还原密钥
103         Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");
104         cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));//设置加密模式并且初始化key,加入IV用于BC下的CTR
105         return cipher.doFinal(data);
106     }
107     
108     /**
109      * AES解密
110      * @param data        待解密数据为字符串
111      * @param keyByte    密钥
112      */
113     public static byte[] decrypt(String data, byte[] keyByte) throws InvalidKeyException, 
114                                                                      NoSuchAlgorithmException, 
115                                                                      InvalidKeySpecException, 
116                                                                      NoSuchPaddingException, 
117                                                                      IllegalBlockSizeException, 
118                                                                      BadPaddingException, 
119                                                                      UnsupportedEncodingException, 
120                                                                      NoSuchProviderException, 
121                                                                      InvalidAlgorithmParameterException {
122         Key key = toKey(keyByte);//还原密钥
123         Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");
124         cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));//设置加密模式并且初始化key,加入IV用于BC下的CTR
125         return cipher.doFinal(Base64.decodeBase64(data));
126     }
127     
128     /**
129      * 测试
130      */
131     public static void main(String[] args) throws NoSuchAlgorithmException, 
132                                                   InvalidKeyException, 
133                                                   InvalidKeySpecException, 
134                                                   NoSuchPaddingException, 
135                                                   IllegalBlockSizeException, 
136                                                   BadPaddingException, 
137                                                   UnsupportedEncodingException, 
138                                                   NoSuchProviderException, 
139                                                   InvalidAlgorithmParameterException {
140         String data = "找一个好姑娘做老婆是我的梦 想!";
141         /*************测试encrypt()、decrypt()**************/
142         System.out.println("原文-->"+data);
143         byte[] keyByte = AESBC.getKey(); 
144         System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
145         byte[] encodedByte = AESBC.encrypt(data, keyByte);
146         System.out.println("加密后-->"+encodedByte);
147         byte[] encodedByte2 = AESBC.encrypt(data, keyByte);
148         System.out.println("加密后-->"+encodedByte2);
149         byte[] decodedByte = AESBC.decrypt(encodedByte, keyByte);
150         System.out.println("解密后-->"+decodedByte);
151         for(int i=0;i<encodedByte.length;i++){
152             System.out.println(encodedByte[i]==encodedByte2[i]);
153         }
154         /*************测试encryptAESHex()、decrypt()**************/
155         System.out.println("原文-->"+data);
156         byte[] keyByte3 = AESBC.getKey(); 
157         System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
158         String encodedStr = AESBC.encryptAESHex(data, keyByte3);
159         System.out.println("加密后-->"+encodedStr);
160         String encodedByte4 = AESBC.encryptAESHex(data, keyByte3);
161         System.out.println("加密后-->"+encodedByte4);
162         byte[] decodedByte3 = AESBC.decrypt(Base64.decodeBase64(encodedStr), keyByte3);
163         System.out.println("解密Byte[]后-->"+decodedByte3);
164         byte[] decodedByte4 = AESBC.decrypt(encodedStr, keyByte3);
165         System.out.println("解密String后-->"+decodedByte4);
166     }
167 }
View Code

 注意点:

  • CTR是AES最常使用的工作模式
  • 在CTR模式下需要加入IV参数(必须是一个16位的自己数组,例如:byte[] IV = "zhaojigangzhaoji".getBytes()),这是ECB模式所不需要的。
  • IV参数用于cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV))

附:无政策限制权限文件配置方法:

第一步:下载配置文件压缩包

http://download.csdn.net/download/rzg813/8069407

第二步:用压缩包中下边选中的文件去覆盖%JAVA_HOME%\jre\lib\security和%JRE_HOME%\lib\security下相应的包即可。

 

posted on 2015-12-29 21:01  赵计刚  阅读(3956)  评论(0编辑  收藏  举报