你的位置:首页 > Java教程

[Java教程]第八章 对称加密算法


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 encryptDESHex(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 = AESBC.getKey(); 145     System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式146     byte[] encodedByte = AESBC.encrypt(data, keyByte);147     System.out.println("加密后-->"+encodedByte);148     byte[] encodedByte2 = AESBC.encrypt(data, keyByte);149     System.out.println("加密后-->"+encodedByte2);150     byte[] decodedByte = AESBC.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     /*************测试encryptDESHex()、decrypt()**************/156     System.out.println("原文-->"+data);157     byte[] keyByte3 = AESBC.getKey(); 158     System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式159     String encodedStr = AESBC.encryptDESHex(data, keyByte3);160     System.out.println("加密后-->"+encodedStr);161     String encodedByte4 = AESBC.encryptDESHex(data, keyByte3);162     System.out.println("加密后-->"+encodedByte4);163     byte[] decodedByte3 = AESBC.decrypt(Base64.decodeBase64(encodedStr), keyByte3);164     System.out.println("解密Byte[]后-->"+decodedByte3);165     byte[] decodedByte4 = AESBC.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不需要配置那个文件)

8.2.2、基于BC的AES实现(工作模式为CTR)

 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 encryptDESHex(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下的CTR105     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下的CTR125     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     /*************测试encryptDESHex()、decrypt()**************/155     System.out.println("原文-->"+data);156     byte[] keyByte3 = AESBC.getKey(); 157     System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式158     String encodedStr = AESBC.encryptDESHex(data, keyByte3);159     System.out.println("加密后-->"+encodedStr);160     String encodedByte4 = AESBC.encryptDESHex(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下相应的包即可。