zoukankan      html  css  js  c++  java
  • java学习-AES加解密之AES-128-CBC算法

    AES算法简介

    AES是一种对称加密算法,或称分组对称加密算法。  是Advanced Encryption Standard高级加密标准,简称AES

    AES的基本要求是,采用对称分组密码体制。分组密码算法通常由密钥扩展算法和加密(解密)算法两部分组成

    AES加密数据块分组长度必须为128比特(bit位),密钥长度可以是128比特、192比特、256比特中的任意一个(如果数据块及密钥长度不足时,会补齐)。

    128位数据块,16byte字节的数据为一组,192位,24字节数据为一组。256位,32字节数据为一组

     

    AES加密有很多轮的重复和变换。大致步骤如下(大概知道步骤就好吧,不想太深入研究):

    1、密钥扩展(KeyExpansion),2、初始轮(Initial Round),3、重复轮(Rounds),

    每一轮又包括:SubBytes、ShiftRows、MixColumns、AddRoundKey,4、最终轮(Final Round),最终轮没有MixColumns。

    AES加密算法有多种加密模式:

    1.电码本模式(Electronic Codebook Book (ECB));2.密码分组链接模式(Cipher Block Chaining (CBC));

    3.计算器模式(Counter (CTR));4.密码反馈模式(Cipher FeedBack (CFB));5.输出反馈模式(Output FeedBack (OFB))。

    ECB:将明文分成若干段相同的小段,然后对每一小段进行加密。

    优点:
    1.简单;
    2.有利于并行计算;
    3.误差不会被传送;
    缺点:
    1.不能隐藏明文的模式;
    2.可能对明文进行主动攻击;


    CBC:这种模式是先将明文切分成若干小段,然后每一小段与初始块或者上一段的密文段进行异或运算后,再与密钥进行加密。

    优点:
    1.不容易主动攻击,安全性好于ECB,适合传输长度长的报文,是SSL、IPSec的标准。
    缺点:
    1.不利于并行计算;
    2.误差传递;
    3.需要初始化向量IV

     参考链接:AES加密的四种模式详解

     AES加密明文数据的5种填充模式

    这些都属于字节填充

      PKCS7Padding(PKCS#7),PKCS5Padding(PKCS#5),Zero padding,ISO 10126 , ANSI X.923

    例如,现在数据128位数据块方式进行加密,即16字节数据,,,现在有字符串String encryptedStr = "012345678912"

      note:由于utf-8下汉字字节长度是可变的,所以直接使用英文或数字字符串举例。

    上面数据的字符串长度为12字节,还需要补充4字节数据。

    ANSIX923是最后一个字节数据为所缺字节的数进行填充,其余填0。上面需要补充4字节数据,所以最后一字节填4,其余3字节都填0

    ISO10126则是最后一字节填4,剩余的都填0,

    PKCS#7 是在填充字节上都填相同的数据,上面数据缺少4字节,所以所有字节上都填4

      如果缺少10字节,则在补充的10字节数据上都填a

    ANSI X.923:... | DD DD DD DD DD DD DD DD | DD DD DD DD (00 00 00 04)|【除了最后字节,其他填0】

    ISO 10126:.... | DD DD DD DD DD DD DD DD | DD DD DD DD (81 A6 23 04)|【除了最后字节,其他随机】

    PKCS7(Rfc3852) | DD DD DD DD DD DD DD DD | DD DD DD DD (04 04 04 04)

    模式说明:(不完整)
    算法/模式/填充                16字节加密后数据长度        不满16字节加密后长度
    AES/CBC/NoPadding             16                          不支持
    AES/CBC/PKCS5Padding          32                          16
    AES/CBC/ISO10126Padding       32                          16
    AES/CFB/NoPadding             16                          原始数据长度
    AES/CFB/PKCS5Padding          32                          16
    AES/CFB/ISO10126Padding       32                          16
    AES/ECB/NoPadding             16                          不支持
    AES/ECB/PKCS5Padding          32                          16
    AES/ECB/ISO10126Padding       32                          16
    AES/OFB/NoPadding             16                          原始数据长度
    AES/OFB/PKCS5Padding          32                          16
    AES/OFB/ISO10126Padding       32                          16
    AES/PCBC/NoPadding            16                          不支持
    AES/PCBC/PKCS5Padding         32                          16
    AES/PCBC/ISO10126Padding      32                          16

    AES-128-CBC加密解密算法 

      这个是使用AES加密算法的CBC模式,使用128位数据块为一组进行加密解密,

    即16字节明文,对应16字节密文,,明文加密时,如果数据不够16字节,则会将数据补全剩余字节

    • 若最后剩余的明文不够16字节,需要进行填充,通常采用PKCS7进行填充。比如最后缺3个字节,则填充3个字节的0x03;若最后缺10个字节,则填充10个字节的0x0a;
    • 若明文正好是16个字节的整数倍,最后要再加入一个16字节0x10的组再进行加密

     加密时需要的参数

    1、传入要加密的明文
    2、传入一个16字节的key
    3、传入一个16字节的初始偏移向量IV
    
    
    
    用初始向量和密钥加密第一组数据,然后把第一组数据加密后的密文重新赋值给IV,然后进行第二组加密,循环进行直到结束

    解密时需要参数

    1、带解密的密文
    2、加密解密的key一致
    3、跟加密时传递IV参数一致

     AES加密解密类

    需要额外的jar包bcprov-jdk16-1.46-sources.jar

    可添加依赖

    <dependency>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk16</artifactId>
                <version>1.46</version>
            </dependency>

    AES.java

    import java.security.AlgorithmParameters;
    import java.security.InvalidKeyException;
    import java.security.Key;
    import java.security.NoSuchProviderException;
    import java.security.Security;
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    public class AES {
    
        //加密方式
        public static String KEY_ALGORITHM = "AES";
        //数据填充方式
        String algorithmStr = "AES/CBC/PKCS7Padding";
        //避免重复new生成多个BouncyCastleProvider对象,因为GC回收不了,会造成内存溢出
        //只在第一次调用decrypt()方法时才new 对象
        public static boolean initialized = false;
    
        /**
         * 
         * @param originalContent
         * @param encryptKey
         * @param ivByte
         * @return
         */
        public byte[] encrypt(byte[] originalContent, byte[] encryptKey, byte[] ivByte) {
            initialize();
            try {
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                SecretKeySpec skeySpec = new SecretKeySpec(encryptKey, "AES");
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(ivByte));
                byte[] encrypted = cipher.doFinal(originalContent);
                return encrypted;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * AES解密
         * 填充模式AES/CBC/PKCS7Padding
         * 解密模式128
         * @param content
         *            目标密文
         * @return
         * @throws Exception 
         * @throws InvalidKeyException 
         * @throws NoSuchProviderException
         */
        public byte[] decrypt(byte[] content, byte[] aesKey, byte[] ivByte) {
            initialize();
            try {
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
                Key sKeySpec = new SecretKeySpec(aesKey, "AES");
                cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
                byte[] result = cipher.doFinal(content);
                return result;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**BouncyCastle作为安全提供,防止我们加密解密时候因为jdk内置的不支持改模式运行报错。**/
        public static void initialize() {
            if (initialized)
                return;
            Security.addProvider(new BouncyCastleProvider());
            initialized = true;
        }
    
        // 生成iv
        public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
            AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
            params.init(new IvParameterSpec(iv));
            return params;
        }
    }

    另一种加密算法DES

    DES算法的入口参数有三个:Key、Data、Mode。

    其中Key为7个字节共56位,是DES算法的工作密钥;

    Data为8个字节64位,是要被加密或被解密的数据;

    Mode为DES的工作方式,有两种:加密或解密。

  • 相关阅读:
    优麒麟(UbuntuKylin)不是国产Linux操作系统
    中间件
    RapeLay(电车之狼R)的结局介绍 (隐藏结局攻略)
    HDU 4284 状压dp+spfa
    素数推断算法(高效率)
    【iOS开发-60】案例学习:多组数据的tableView设置、添加右側组索引、多层数据模型设置以及valueForKeyPath
    理解class.forName()
    Oracle经典查询案例
    Java抓取网页数据(原网页+Javascript返回数据)
    破解windows下MySQL服务启动不了的情况下不能对其进行全然卸载的解决方式
  • 原文地址:https://www.cnblogs.com/gne-hwz/p/9553502.html
Copyright © 2011-2022 走看看