AES是基于数据块的加密方式,即每次处理的数据是一块(16字节),当数据不是16字节的倍数时填充,这就是所谓的分组密码(区别于基于比特位的流密码),16字节是分组长度。

AES支持五种模式:CBC,CFB,ECB,OFB,PCBC,

jce中实现了三种补码方式:NoPadding,PKCS5Padding,ISO10126Padding;不支持SSL3Padding,不支持“NONE”模式。

ECB:是一种基础的加密方式,密文被分割成分组长度相等的块(不足补齐),然后单独一个个加密,一个个输出组成密文。

CBC:是一种循环模式,前一个分组的密文和当前分组的明文异或操作后再加密,这样做的目的是增强破解难度。

CFB/OFB实际上是一种反馈模式,目的也是增强破解的难度。

ECB和CBC的加密结果是不一样的,两者的模式不同,而且CBC会在第一个密码块运算时加入一个初始化向量。

算法/模式/填充16字节加密后数据长度
不满16字节加密后长度
AES/CBC/NoPadding16
不支持
AES/CBC/PKCS5Padding32
16
AES/CBC/ISO10126Padding32
16
AES/CFB/NoPadding16
原始数据长度
AES/CFB/PKCS5Padding32
16
AES/CFB/ISO10126Padding32
16
AES/ECB/NoPadding16
不支持
AES/ECB/PKCS5Padding32
16
AES/ECB/ISO10126Padding32
16
AES/OFB/NoPadding16
原始数据长度
AES/OFB/PKCS5Padding32
16
AES/OFB/ISO10126Padding32
16
AES/PCBC/NoPadding16
不支持
AES/PCBC/PKCS5Padding32
16
AES/PCBC/ISO10126Padding32
16

AES-128-CBC方式与AES-128方式不同的地方:

AES-128-CBC可以自己定义“密钥”和“偏移量“,AES-128是jdk自动生成的“密钥”,所以AES-128-CBC更灵活。

代码实例:

package com.client;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; /**AES 是一种可逆加密算法,对用户的敏感信息加密处理
* 对原始数据进行AES加密后,在进行Base64编码转化;
*/
public class AesCBC {
    /*
    * 加密用的Key 可以用26个字母和数字组成
    * 此处使用AES-128-CBC加密模式,key需要为16位。
    */
    private static String sKey = "sklhdflsjfsdgdeg";
    private static String ivParameter = "cfbsdfgsdfxccvd1";
    private static AesCBC instance = null;     private AesCBC() {
    }     public static AesCBC getInstance() {
        if (instance == null) {
            instance = new AesCBC();
        }
        return instance;
    }     // 加密
    public String encrypt(String sSrc, String encodingFormat, String sKey,
        String ivParameter) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] raw = sKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes()); //使用CBC模式,需要一个向量iv,可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes(encodingFormat));
        return new BASE64Encoder().encode(encrypted); //此处使用BASE64做转码。
    }     // 解密
    public String decrypt(String sSrc, String encodingFormat, String sKey,
        String ivParameter) throws Exception {
        try {
            byte[] raw = sKey.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc); //先用base64解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, encodingFormat);
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }     public static void main(String[] args) throws Exception {
        // 需要加密的字串
        String cSrc = "我来自中国";
        System.out.println(cSrc);         // 加密
        long lStart = System.currentTimeMillis();
        String enString = AesCBC.getInstance()
                                .encrypt(cSrc, "utf-8", sKey, ivParameter);
        System.out.println("加密后的字串是:" + enString);
        long lUseTime = System.currentTimeMillis() - lStart;
        System.out.println("加密耗时:" + lUseTime + "毫秒");
        // 解密
        lStart = System.currentTimeMillis();
        String DeString = AesCBC.getInstance()
                                .decrypt(enString, "utf-8", sKey, ivParameter);
        System.out.println("解密后的字串是:" + DeString);
        lUseTime = System.currentTimeMillis() - lStart;
        System.out.println("解密耗时:" + lUseTime + "毫秒");
    }
}

使用AES-CBC-PKCS7Padding 加解密字符串

java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别,PKCS5Padding的blocksize为8字节,而PKCS7Padding的blocksize可以为1到255字节。

要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现。

bcprov-jdk16-146.jar

加密代码如下:

/**
 *
 * @author ngh
 * AES128 算法
 *
 * CBC 模式
 *
 * PKCS7Padding 填充模式
 *
 * CBC模式需要添加一个参数iv
 *
 * 介于java 不支持PKCS7Padding,只支持PKCS5Padding 但是PKCS7Padding 和 PKCS5Padding 没有什么区别
 * 要实现在java端用PKCS7Padding填充,需要用到bouncycastle组件来实现
 */
public class AES {
    // 算法名称
    final String KEY_ALGORITHM = "AES";     // 加解密算法/模式/填充方式
    final String algorithmStr = "AES/CBC/PKCS7Padding";
    //
    private Key key;
    private Cipher cipher;
    boolean isInited = false;
    byte[] iv = {
            0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30,
            0x36, 0x30, 0x37, 0x30, 0x38
        };     public void init(byte[] keyBytes) {
        // 如果密钥不足16位,那么就补足.  这个if 中的内容很重要
        int base = 16;
        if ((keyBytes.length % base) != 0) {
            int groups = (keyBytes.length / base) +
                (((keyBytes.length % base) != 0) ? 1 : 0);
            byte[] temp = new byte[groups * base];
            Arrays.fill(temp, (byte) 0);
            System.arraycopy(keyBytes, 0, temp, 0, keyBytes.length);
            keyBytes = temp;
        }         // 初始化
        Security.addProvider(new BouncyCastleProvider());
        // 转化成JAVA的密钥格式
        key = new SecretKeySpec(keyBytes, KEY_ALGORITHM);
        try {
            // 初始化cipher
            cipher = Cipher.getInstance(algorithmStr, "BC");
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }     /**
     * 加密方法
     *
     * @param content
     *            要加密的字符串
     * @param keyBytes
     *            加密密钥
     * @return
     */
    public byte[] encrypt(byte[] content, byte[] keyBytes) {
        byte[] encryptedText = null;
        init(keyBytes);
        System.out.println("IV:" + new String(iv));
        try {
            cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
            encryptedText = cipher.doFinal(content);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return encryptedText;
    }     /**
     * 解密方法
     *
     * @param encryptedData
     *            要解密的字符串
     * @param keyBytes
     *            解密密钥
     * @return
     */
    public byte[] decrypt(byte[] encryptedData, byte[] keyBytes) {
        byte[] encryptedText = null;
        init(keyBytes);
        System.out.println("IV:" + new String(iv));
        try {
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            encryptedText = cipher.doFinal(encryptedData);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return encryptedText;
    }
}

测试代码如下:

public class Test {
    public static void main(String[] args) {
        AES aes = new AES();
        //   加解密 密钥
        byte[] keybytes = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
        String content = "1";
        // 加密字符串
        System.out.println("加密前的:" + content);
        System.out.println("加密密钥:" + new String(keybytes));
        // 加密方法
        byte[] enc = aes.encrypt(content.getBytes(), keybytes);
        System.out.println("加密后的内容:" + new String(Hex.encode(enc)));
        // 解密方法
        byte[] dec = aes.decrypt(enc, keybytes);
        System.out.println("解密后的内容:" + new String(dec));
    }
}

AES学习小结的更多相关文章

  1. flex学习小结

    接触到flex一个多月了,今天做一个学习小结.如果有知识错误或者意见不同的地方.欢迎交流指教. 画外音:先说一下,我是怎么接触到flex布局的.对于正在学习的童鞋们,我建议大家没事可以逛逛网站,看看人 ...

  2. Python 学习小结

    python 学习小结 python 简明教程 1.python 文件 #!/etc/bin/python #coding=utf-8 2.main()函数 if __name__ == '__mai ...

  3. react学习小结(生命周期- 实例化时期 - 存在期- 销毁时期)

    react学习小结   本文是我学习react的阶段性小结,如果看官你是react资深玩家,那么还请就此打住移步他处,如果你想给一些建议和指导,那么还请轻拍~ 目前团队内对react的使用非常普遍,之 ...

  4. objective-c基础教程——学习小结

    objective-c基础教程——学习小结   提纲: 简介 与C语言相比要注意的地方 objective-c高级特性 开发工具介绍(cocoa 工具包的功能,框架,源文件组织:XCode使用介绍) ...

  5. pthread多线程编程的学习小结

    pthread多线程编程的学习小结  pthread 同步3种方法: 1 mutex 2 条件变量 3 读写锁:支持多个线程同时读,或者一个线程写     程序员必上的开发者服务平台 —— DevSt ...

  6. ExtJs学习笔记之学习小结LoginDemo

    ExtJs学习小结LoginDemo 1.示例:(登录界面) <!DOCTYPE html> <html> <head> <meta charset=&quo ...

  7. 点滴的积累---J2SE学习小结

    点滴的积累---J2SE学习小结 什么是J2SE J2SE就是Java2的标准版,主要用于桌面应用软件的编程:包括那些构成Java语言核心的类.比方:数据库连接.接口定义.输入/输出.网络编程. 学习 ...

  8. (转) Parameter estimation for text analysis 暨LDA学习小结

    Reading Note : Parameter estimation for text analysis 暨LDA学习小结 原文:http://www.xperseverance.net/blogs ...

  9. dubbo学习小结

    dubbo学习小结 参考: https://blog.csdn.net/paul_wei2008/article/details/19355681 https://blog.csdn.net/liwe ...

随机推荐

  1. DEDECMS打开网站后台系统首页卡解决方法

    找到根目录下(一般是dede) templets文件夹下找到index_body.htm文件,将第25行至第41行部分注释或删除 保存文件,然后再打开后台,就不会有这个问题了.

  2. dede:list 与 dede:arclist 的区别

    1.{dede:list}是用于列表页的文章列表调用,通常是用于list_article.htm页面,这个文章列表是可以分页的. 功能说明:表示列表模板里的分页内容列表适用范围:仅列表模板 list_ ...

  3. abstract和interface关键字介绍

    一.abstract关键字介绍 abstract可以修饰方法.类.使用abstract修饰的方法和类分别叫做抽象方法和抽象类. 1.抽象方法 抽象方法的定义:指可以通过abstract关键字声明的方法 ...

  4. 四、React创建组件、 JSX使用、绑定数据、引用图片方式、数组(列表)循环输出

    接:https://www.cnblogs.com/chenxi188/p/11702799.html 用上节建好的my-app项目: my-app/ README.md node_modules/ ...

  5. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-text-width

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  6. Sklearn 预处理数据

    ## 版权所有,转帖注明出处 章节 SciKit-Learn 加载数据集 SciKit-Learn 数据集基本信息 SciKit-Learn 使用matplotlib可视化数据 SciKit-Lear ...

  7. TD信息通(无课表)使用体验

    首先,在注册账户的时候,TD信息通还是比较严谨的.用户名字符数.密码字符数.邮箱格式等都有要求,我认为,这对App的长远发展来说,是很重要的一个细节.而且,在登陆之前,会有一项关于是否自动登陆的选择, ...

  8. Mac安装vue产生错误

    npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules/webpack/node_modules/_ ...

  9. javascript面向对象编程的3种常见封装形式解析

    javascript如何才能脱离函数式编程,拥抱面向对象编程呢,常见的有3种形式,其它形式可以说都是这3种的变种.   1.直接定义对象直接量的形式   var Util={     getType: ...

  10. HZNU-ACM寒假集训Day5小结 线段树 树状数组

    线段树 什么时候用线段树 1.统计量可合并 2.修改量可合并 3.通过统计量可直接修改统计量 一句话:满足区间加法即可使用线段树维护信息 理解Lazy Tage 蓝色是要把信息及时维护的节点,红色是本 ...