注意:本节内容主要参考自《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)

package com.util.aes;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;

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.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * 基于JDK或BC的AES算法,工作模式采用ECB
 */
public class AESJDK {
    private static final String ENCODING = "UTF-8";
    private static final String KEY_ALGORITHM = "AES";//产生密钥的算法
    private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";//加解密算法 格式:算法/工作模式/填充模式 注意:ECB不使用IV参数
    /**
     * 产生密钥
     */
    public static byte[] getKey() throws NoSuchAlgorithmException{
        Security.addProvider(new BouncyCastleProvider());//在BC中用,JDK下去除
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
        keyGenerator.init(256);//初始化密钥长度,128,192,256(选用192和256的时候需要配置无政策限制权限文件--JDK6)
        SecretKey key =keyGenerator.generateKey();//产生密钥
        return key.getEncoded();
    }

    /**
     * 还原密钥:二进制字节数组转换为Java对象
     */
    public static Key toKey(byte[] keyByte){
        return new SecretKeySpec(keyByte, KEY_ALGORITHM);
    }

    /**
     * AES加密
     * @param data     带加密数据
     * @param keyByte  密钥
     */
    public static byte[] encrypt(String data, byte[] keyByte) throws InvalidKeyException,
                                                                     NoSuchAlgorithmException,
                                                                     InvalidKeySpecException,
                                                                     NoSuchPaddingException,
                                                                     IllegalBlockSizeException,
                                                                     BadPaddingException,
                                                                     UnsupportedEncodingException,
                                                                     NoSuchProviderException,
                                                                     InvalidAlgorithmParameterException{
        Key key = toKey(keyByte);//还原密钥
        //Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//JDK下用
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
        cipher.init(Cipher.ENCRYPT_MODE, key);//设置加密模式并且初始化key
        return cipher.doFinal(data.getBytes(ENCODING));
    }

    /**
     * AES加密,并转为16进制字符串或Base64编码字符串
     */
    public static String encryptAESHex(String data, byte[] keyByte) throws InvalidKeyException,
                                                                           NoSuchAlgorithmException,
                                                                           InvalidKeySpecException,
                                                                           NoSuchPaddingException,
                                                                           IllegalBlockSizeException,
                                                                           BadPaddingException,
                                                                           UnsupportedEncodingException,
                                                                           NoSuchProviderException,
                                                                           InvalidAlgorithmParameterException {
        byte[] encodedByte = encrypt(data, keyByte);
        //return new String(Hex.encode(encodedByte));//借助BC
        //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
        return Base64.encodeBase64String(encodedByte);//借助CC的Base64编码
    }

    /**
     * AES解密
     * @param data        待解密数据为字节数组
     * @param keyByte    密钥
     */
    public static byte[] decrypt(byte[] data, byte[] keyByte) throws InvalidKeyException,
                                                                     NoSuchAlgorithmException,
                                                                     InvalidKeySpecException,
                                                                     NoSuchPaddingException,
                                                                     IllegalBlockSizeException,
                                                                     BadPaddingException,
                                                                     UnsupportedEncodingException,
                                                                     NoSuchProviderException,
                                                                     InvalidAlgorithmParameterException {
        Key key = toKey(keyByte);//还原密钥
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
        //Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//JDK下用
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(data);
    }

    /**
     * AES解密
     * @param data        待解密数据为字符串
     * @param keyByte    密钥
     */
    public static byte[] decrypt(String data, byte[] keyByte) throws InvalidKeyException,
                                                                     NoSuchAlgorithmException,
                                                                     InvalidKeySpecException,
                                                                     NoSuchPaddingException,
                                                                     IllegalBlockSizeException,
                                                                     BadPaddingException,
                                                                     UnsupportedEncodingException,
                                                                     NoSuchProviderException,
                                                                     InvalidAlgorithmParameterException {
        Key key = toKey(keyByte);//还原密钥
        //Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);//JDK下用
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//BC下用
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(Base64.decodeBase64(data));//注意data不可以直接采用data.getByte()方法转化为字节数组,否则会抛异常
    }

    /**
     * 测试
     */
    public static void main(String[] args) throws NoSuchAlgorithmException,
                                                  InvalidKeyException,
                                                  InvalidKeySpecException,
                                                  NoSuchPaddingException,
                                                  IllegalBlockSizeException,
                                                  BadPaddingException,
                                                  UnsupportedEncodingException,
                                                  NoSuchProviderException,
                                                  InvalidAlgorithmParameterException {
        String data = "找一个好姑娘做老婆是我的梦 想!";
        /*************测试encrypt()、decrypt()**************/
        System.out.println("原文-->"+data);
        byte[] keyByte = AESJDK.getKey();
        System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
        byte[] encodedByte = AESJDK.encrypt(data, keyByte);
        System.out.println("加密后-->"+encodedByte);
        byte[] encodedByte2 = AESJDK.encrypt(data, keyByte);
        System.out.println("加密后-->"+encodedByte2);
        byte[] decodedByte = AESJDK.decrypt(encodedByte, keyByte);
        System.out.println("解密后-->"+decodedByte);
        for(int i=0;i<encodedByte.length;i++){
            System.out.println(encodedByte[i]==encodedByte2[i]);
        }
        /*************测试encryptAESHex()、decrypt()**************/
        System.out.println("原文-->"+data);
        byte[] keyByte3 = AESJDK.getKey();
        System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
        String encodedStr = AESJDK.encryptAESHex(data, keyByte3);
        System.out.println("加密后-->"+encodedStr);
        String encodedByte4 = AESJDK.encryptAESHex(data, keyByte3);
        System.out.println("加密后-->"+encodedByte4);
        byte[] decodedByte3 = AESJDK.decrypt(Base64.decodeBase64(encodedStr), keyByte3);
        System.out.println("解密Byte[]后-->"+decodedByte3);
        byte[] decodedByte4 = AESJDK.decrypt(encodedStr, keyByte3);
        System.out.println("解密String后-->"+decodedByte4);
    }
}

注意点:

  • 本文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算法的话,用上边那种就好)

package com.util.aes;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;

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.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

/**
 * 基于BC的AES算法,工作模式采用CTR
 */
public class AESBC {
    private static final String ENCODING = "UTF-8";
    private static final String KEY_ALGORITHM = "AES";//产生密钥的算法
    private static final String CIPHER_ALGORITHM = "AES/CTR/PKCS7Padding";//加解密算法 格式:算法/工作模式/填充模式 注意:ECB不使用IV参数,CTR使用
    private static final byte[] IV = "zhaojigangzhaoji".getBytes();//注意:这里需要是十六个字符,用于CTR
    /**
     * 产生密钥
     */
    public static byte[] getKey() throws NoSuchAlgorithmException{
        Security.addProvider(new BouncyCastleProvider());//加入BCProvider
        KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
        keyGenerator.init(256);//初始化密钥长度,128,192,256(选用192和256的时候需要配置无政策限制权限文件--JDK6)
        SecretKey key =keyGenerator.generateKey();//产生密钥
        return key.getEncoded();
    }

    /**
     * 还原密钥:二进制字节数组转换为Java对象
     */
    public static Key toKey(byte[] keyByte){
        return new SecretKeySpec(keyByte, KEY_ALGORITHM);
    }

    /**
     * AES加密
     * @param data     带加密数据
     * @param keyByte  密钥
     */
    public static byte[] encrypt(String data, byte[] keyByte) throws InvalidKeyException,
                                                                     NoSuchAlgorithmException,
                                                                     InvalidKeySpecException,
                                                                     NoSuchPaddingException,
                                                                     IllegalBlockSizeException,
                                                                     BadPaddingException,
                                                                     UnsupportedEncodingException,
                                                                     NoSuchProviderException,
                                                                     InvalidAlgorithmParameterException{
        Key key = toKey(keyByte);//还原密钥
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");//使用BC
        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));//设置加密模式并且初始化key,加入IV用于BC下的CTR
        return cipher.doFinal(data.getBytes(ENCODING));
    }

    /**
     * AES加密,并转为16进制字符串或Base64编码字符串
     */
    public static String encryptAESHex(String data, byte[] keyByte) throws InvalidKeyException,
                                                                           NoSuchAlgorithmException,
                                                                           InvalidKeySpecException,
                                                                           NoSuchPaddingException,
                                                                           IllegalBlockSizeException,
                                                                           BadPaddingException,
                                                                           UnsupportedEncodingException,
                                                                           NoSuchProviderException,
                                                                           InvalidAlgorithmParameterException {
        byte[] encodedByte = encrypt(data, keyByte);
        //return new String(Hex.encode(encodedByte));//借助BC
        //return new String(org.apache.commons.codec.binary.Hex.encodeHexString(encodedByte));//借助CC
        return Base64.encodeBase64String(encodedByte);//借助CC的Base64编码
    }

    /**
     * AES解密
     * @param data        待解密数据为字节数组
     * @param keyByte    密钥
     */
    public static byte[] decrypt(byte[] data, byte[] keyByte) throws InvalidKeyException,
                                                                     NoSuchAlgorithmException,
                                                                     InvalidKeySpecException,
                                                                     NoSuchPaddingException,
                                                                     IllegalBlockSizeException,
                                                                     BadPaddingException,
                                                                     UnsupportedEncodingException,
                                                                     NoSuchProviderException,
                                                                     InvalidAlgorithmParameterException {
        Key key = toKey(keyByte);//还原密钥
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");
        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));//设置加密模式并且初始化key,加入IV用于BC下的CTR
        return cipher.doFinal(data);
    }

    /**
     * AES解密
     * @param data        待解密数据为字符串
     * @param keyByte    密钥
     */
    public static byte[] decrypt(String data, byte[] keyByte) throws InvalidKeyException,
                                                                     NoSuchAlgorithmException,
                                                                     InvalidKeySpecException,
                                                                     NoSuchPaddingException,
                                                                     IllegalBlockSizeException,
                                                                     BadPaddingException,
                                                                     UnsupportedEncodingException,
                                                                     NoSuchProviderException,
                                                                     InvalidAlgorithmParameterException {
        Key key = toKey(keyByte);//还原密钥
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM,"BC");
        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV));//设置加密模式并且初始化key,加入IV用于BC下的CTR
        return cipher.doFinal(Base64.decodeBase64(data));
    }

    /**
     * 测试
     */
    public static void main(String[] args) throws NoSuchAlgorithmException,
                                                  InvalidKeyException,
                                                  InvalidKeySpecException,
                                                  NoSuchPaddingException,
                                                  IllegalBlockSizeException,
                                                  BadPaddingException,
                                                  UnsupportedEncodingException,
                                                  NoSuchProviderException,
                                                  InvalidAlgorithmParameterException {
        String data = "找一个好姑娘做老婆是我的梦 想!";
        /*************测试encrypt()、decrypt()**************/
        System.out.println("原文-->"+data);
        byte[] keyByte = AESBC.getKey();
        System.out.println("密钥-->"+Base64.encodeBase64String(keyByte));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
        byte[] encodedByte = AESBC.encrypt(data, keyByte);
        System.out.println("加密后-->"+encodedByte);
        byte[] encodedByte2 = AESBC.encrypt(data, keyByte);
        System.out.println("加密后-->"+encodedByte2);
        byte[] decodedByte = AESBC.decrypt(encodedByte, keyByte);
        System.out.println("解密后-->"+decodedByte);
        for(int i=0;i<encodedByte.length;i++){
            System.out.println(encodedByte[i]==encodedByte2[i]);
        }
        /*************测试encryptAESHex()、decrypt()**************/
        System.out.println("原文-->"+data);
        byte[] keyByte3 = AESBC.getKey();
        System.out.println("密钥-->"+Base64.encodeBase64String(keyByte3));//这里将二进制的密钥使用base64加密保存,这也是在实际中使用的方式
        String encodedStr = AESBC.encryptAESHex(data, keyByte3);
        System.out.println("加密后-->"+encodedStr);
        String encodedByte4 = AESBC.encryptAESHex(data, keyByte3);
        System.out.println("加密后-->"+encodedByte4);
        byte[] decodedByte3 = AESBC.decrypt(Base64.decodeBase64(encodedStr), keyByte3);
        System.out.println("解密Byte[]后-->"+decodedByte3);
        byte[] decodedByte4 = AESBC.decrypt(encodedStr, keyByte3);
        System.out.println("解密String后-->"+decodedByte4);
    }
}

注意点:

  • 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下相应的包即可。

第八章 对称加密算法--AES的更多相关文章

  1. JAVA的对称加密算法AES——加密和解密

    出自: http://blog.csdn.net/hongtashan11/article/details/6599645 http://www.cnblogs.com/liunanjava/p/42 ...

  2. DES、3DES、AES、PBE对称加密算法实现及应用

    1.对称加密算法概述 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文和加密密钥一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去.收信方收到密文后,若想解读原文 ...

  3. 常用加密算法的Java实现总结(二) ——对称加密算法DES、3DES和AES

    1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...

  4. Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES RSA

    版权声明:本文为博主原创文章,未经博主允许不得转载. [前言] 本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及使用方法和例子 [最简单的加密] 1.简单的概念 明文:加密前的 ...

  5. Java 加密 AES 对称加密算法

    版权声明:本文为博主原创文章,未经博主允许不得转载. [AES] 一种对称加密算法,DES的取代者. 加密相关文章见:Java 加密解密 对称加密算法 非对称加密算法 MD5 BASE64 AES R ...

  6. 对称加密算法DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES。

    对称加密算法:DES,3重DES,TDEA,Blowfish,RC5,IDEA,AES. 1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文 ...

  7. java-信息安全(二)-对称加密算法DES,3DES,AES,Blowfish,RC2,RC4

    概述 信息安全基本概念: DES(Data Encryption Standard,数据加密标准) 3DES(Triple DES,三重数据加密算法(TDEA,Triple Data Encrypti ...

  8. 对称加密算法DES、3DES和AES 原理总结(转载)

    1.对称加密算法 1.1 定义 对称加密算法是应用较早的加密算法,技术成熟.在对称加密算法中,数据发信方将明文(原始数据)和加密密钥(mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发 ...

  9. DES/3DES/AES 三种对称加密算法实现

    1. 简单介绍 3DES(或称为Triple DES)是三重数据加密算法(TDEA,Triple Data Encryption Algorithm)块密码的通称.它相当于是对每个数据块应用三次DES ...

随机推荐

  1. ChinaTest测试感悟

    这次去北京参加ChinaTest大会,听了各位大师和同行的心得和感悟,收获颇多.很喜欢这样的大会,可以听到测试的各种声音各种观点.当没有对错时,需要思考的就是怎样采取最适合当前环境的策略.言归正传,谈 ...

  2. sublime eslint 和 jshint的安装与使用

    jshint简介 jslint是一javascript的语法检测,众多前端自动化工具都又用到,编辑器也用到jshint. webstorm很强大,自身带有,但是我使用的电脑带不动.sublime或者a ...

  3. mysql transaction 事务

    1.事务简介 一个"最小的"不可再分的"工作单元". 一个事务通常对应了一个完整的业务.如:银行的转账功能,a转账给b,a扣钱,b加钱. 一个事务包含一条或多条 ...

  4. mysql 数据操作 多表查询 目录

    mysql 数据操作 多表查询 准备 多表连接查询介绍 mysql 数据操作 多表查询 多表连接查询 笛卡尔积 mysql 数据操作 多表查询 多表连接查询 内连接 mysql 数据操作 多表查询 多 ...

  5. adb server version (31) doesn't match this client (36)

    运行adb 命令的时候报错: C:\Users\Administrator>adb devices List of devices attachedadb server version (31) ...

  6. vue-moment的使用

    1.安装:npm install moment --save 2.导入:import moment from 'moment'; 3.定义全局时间过滤器:  Vue.filter('converDat ...

  7. windows server r2 搭建 ftp服务器

    1:安装ftp服务器 开始>管理工具>服务器管理器>打开服务器管理器,找到添加角色,然后点击,弹出添加角色对话框,选择下一步>选择Web服务器(IIS),然后选择FTP服务,直 ...

  8. HTTP权威指南读书笔记

    HTTP权威指南笔记 读书有两种境界,第一种境界是将书读薄,另一种是读厚.本篇文章就是HTTP权威指南的读书笔记,算是读书的第一重境界,将厚书读薄.文章对HTTP的一些关键概念做了比较详细的概述,通读 ...

  9. 2018-2019-2 网络对抗技术 20165324 Exp2: 后门原理与实践

    2018-2019-2 网络对抗技术 20165324 Exp2: 后门原理与实践 课程学习: 后门 后门:是不经过正常认证流程而访问系统的通道,存在与编译器.操作系统.固件和应用中等等. 后门工作流 ...

  10. FRM-92095: Oracle Jnitiator version too low – please install version 1.1.8.2 or higher

    打开EBS,系统报:FRM-92095: Oracle JInitiator 版本太旧. 请安装版本1.1.8.2或更高版本 (英文的错误信息是:FRM-92095: Oracle JInitiato ...