zoukankan      html  css  js  c++  java
  • 第八章 对称加密算法--AES

    注意:本节内容主要参考自《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%jrelibsecurity和%JRE_HOME%libsecurity下相应的包即可。

  • 相关阅读:
    在没有备份的情况下重新创建丢失的数据文件 (Doc ID 1149946.1)
    How to recover a skipped tablespace after an incomplete recovery? (Doc ID 1561645.1)
    RMAN DUPLICATE DATABASE with SET NEWNAME failed: RMAN-05501 RMAN-05517 (Doc ID 387093.1)
    Rman Enhancements(增强) In Oracle 11g. (Doc ID 1115423.1)
    Resolving RMAN-06023 or RMAN-06025 (Doc ID 2038119.1)
    Checklist for an RMAN Restore (Doc ID 1554636.1)
    Recover With Until Time fails With RMAN-20207 When Time Is Before Last RESETLOGS (Doc ID 159405.1)
    ODA: After Apply ODA 12.2.1.2.0 Patch, Unable to Create TableSpace Due to [ORA-15001: diskgroup "DATA" does not exist or is not mounted | ORA-15040: diskgroup is incomplete] (Doc ID 2375553.1)
    How to restore and recover a database from an RMAN backup. (Doc ID 881395.1)
    How To Restore Rman Backups On A Different Node When The Directory Structures Are Different (Doc ID 419137.1)
  • 原文地址:https://www.cnblogs.com/java-zhao/p/5087046.html
Copyright © 2011-2022 走看看