AES算法详解

AES算法详解

  • 认识AES
    • 什么是AES
    • AES简介
    • AES的加密模式及个模式加密的优缺点
  • AES算法加密过程
    • 明文块的生成
    • 加密的基本步骤
  • 初始变换
    • 拓展轮密钥
      • 拓展原因及使用顺序
      • 生成规则
        • 字循环
        • 字节代换
        • 轮常量异或
  • 9轮中间变换
    • 字节代换
    • 行移位
    • 列混合
    • 轮密钥加
  • 最后一轮变换
  • 密文矩阵转为密文
  • 简单使用Java封装的AES算法
    • 使用到的类及其基本的方法
      • KeyGenerator.class
      • SecretKey.class
      • SecretKeySpec.class
      • Cipher.class
    • Java中AES算法的简单使用
      • 简单使用
  • 参考资料

认识AES

什么是AES

密码学中的高级加密标准(Advanced Encryption Standard,AES),又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准

AES简介

这个标准用来替代原先的DES(Data Encryption Standard),已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院 (NIST)于2001年11月26日发布于FIPS PUB 197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一 [1] 。
该算法为比利时密码学家Joan Daemen和Vincent Rijmen所设计,结合两位作者的名字,以Rijdael之名命之,投稿高级加密标准的甄选流程。(Rijdael的发音近于 “Rhine doll”。)

AES的加密模式及个模式加密的优缺点

AES的分组长度是128bit,三种可选密钥长度128bit,192bit和256bit,轮数分别为10、12和14
常见五中工作模式:

ECB (ElectronicCodebook,电子密码本)
优点:简单、可并行计算、误差不传递
缺点:不能隐藏明文模式(比如图像加密轮廓仍在)、主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)
用途:需要并行加密的应用

CBC (Cipher Block Chaining,密码分组链接)∶
优点:不容易主动攻击(误差传递)、适合长报文,是SSL、IPSec标准
缺点:无法并行、误差传递
用途:长报文传输,SSL和IPSec

CFB (CipherFeedback,密码反馈)︰
优点:不容易主动攻击(误差传递),分组转变为流模式,可加密小于分组数据缺点:无法并行、误差传递

OFB (OutputFeedback,输出反馈)︰
优点:分组转为流模式、可加密小于分组数据
缺点:主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)
用途:通信信道质量不高时使用,比如卫星通信

CTR (Counter,计数器模式)∶
描述:计算器模式不常见,在CTR模式中,有一个自增的算子,这个算子用密钥加密之后的输出和明文异或的结果得到密文,相当于一次一密。这种加密方式简单快速,安全可靠,而且可以并行加密,但是在计算器不能维持很长的情况下,密钥只能使用一次
优点:并行、一次一密、不传递误差
缺点:主动攻击(改明文,后续内容不影响,只要误差不传递该缺点就存在)

总结

分组模式: ECB、CBC和CTR;
模式: CFB、OFB

传递误差: CBC、CFB
不传递误差: ECB、OFB和CTR

可并行: ECB、CTR
不可并行: CBC、OFB、CFB

AES算法加密过程

明文块的生成

我们输入的明文会被分割成大小相同的明文块,一个明文块大小为16字节、128位,如果最后一块小于16k那就需要涉及填充和链加密模式了。
假设明文块为:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
上述明文块按照顺序,从上往下,从左到右变换成以下明文矩阵
0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15
每个位置占8位,第n个字节对应的位置(i , j)可以按以下方式计算
i = n%4;
j = n/4;(向下取整)
n = i + 4j;

同样的,密钥也是16字节 128位

加密的基本步骤

AES算法详解_第1张图片

其中的明文矩阵为字节表示的4x4的矩阵,而状态矩阵是将明文矩阵转为十六进制后的矩阵。

初始变换

一个明文块16k 转变成 4 X 4(16进制)的矩阵,与子密钥生成的初始矩阵4 X 4(16进制),做一个异或

拓展轮密钥

拓展原因及使用顺序

由于后续要做10轮加密操作,每轮都要使用一个4X4的矩阵。那么单单一个子密钥生成的4X4的矩阵自然是不够的,所以需要对密钥做扩展。也就是把4X4字节的子密钥 ——> 4X43轮密钥,从4列扩展为44列(这里需要注意的是: 初始变换已经用了第0列到第三列,所以10轮加密从第4列开始取

比如第i轮(i ∈ [1,10])加密,使用第4i到 4i + 3列的数据作为子密钥矩阵。第1轮,使用第4列,到第4 + 3列,最后一轮使用第40列,到43列作为密钥矩阵。

生成规则

假设i是我们要生成的扩展子密钥列数,如果 i 为四的倍数,那么该列:Wi = Wi-4 ⊕ T(Wi-1)
其中T函数表示三个操作:

字循环

将Wi-1列赋值到 Wi上,列【b0, b1, b2 ,b3】更改为 【b1 , b2 , b3 , b0】(注意,这里是列,应该是竖起来的,我这里为了方便所以是横的

字节代换

使用S盒代换,与下面的S_Box一致

轮常量异或

与同轮(第一轮和常量矩阵第一列 第二轮和常量矩阵第二列),给定的矩阵进行同列⊕。可以看出每列对应的i为:4 8 12 16 20 24 28 32 36 40
AES算法详解_第2张图片

当i不是四的倍数时:Wi = Wi-4 ⊕ Wi-1,只做一个异或

9轮中间变换

字节代换

S-box的替换。比如00,表示用 第0行 第0列 对应的是0x63 ,所以00替换成63。 这里的0x表示的是十六进制
AES算法详解_第3张图片

行移位

除开第一行第二行往左移动一位第二行往左移动第二位第三行往左移动第三位。(只算明文列数4–也就是128字节)

列混合

AES算法详解_第4张图片

左乘一个给定的 4 X 4矩阵,进行单个结果有限域上的二元运算(GF2^8)
可以点这里详细了解X乘运算.

轮密钥加

与密钥扩展得到的10轮密钥中的一组逐字节做异或与对应位置上的数据做一个异或)。比如明文状态矩阵为4列(即明文块占128位 16字节),第 i 轮选取轮密钥的W[ 4 * i ] ~ W[ 4* i + 3]。 比如第一轮 i=1.那么取的轮密钥矩阵中的是4 ~ 7列。

最后一轮变换

与前九轮相比 最后一轮没有列混合,其他三位操作一样。

密文矩阵转为密文

然后将得到的密文矩阵转为密文状态矩阵再转为密文输出。

简单使用Java封装的AES算法

使用到的类及其基本的方法

JDK链接,有兴趣的自己详细了解。下文只介绍简单使用涉及到类以及方法。

KeyGenerator.class

该类提供了一个对称密钥生成器的功能。

//生成一个AES算法的密钥生成器
KeyGenerator kg = KeyGenerator.getInstance("AES");
//使用给定字节数组生成安全随机密码对象,并用该对象初始化该密钥生成器(生成密钥长度为128位)
kg.init(128, new SecureRandom(rule.getBytes("UTF-8")));
//生成一个种子密钥。
SecretKey ruleKey = kg.generateKey();

SecretKey.class

该接口的目的是为所有密钥(不同算法的密钥)接口分组。

SecretKeySpec.class

它可以用于从字节数组构造一个SecretKey 。

 //从给定的字节数组构造一个aes密钥 skCode为给定的字节数组 按AES算法生成密钥
SecretKey aesKey = new SecretKeySpec(skCode , "AES");

Cipher.class

该类提供主要的加密、解密操作。

//获取实例
Cipher cp = Cipher.getInstance("AES");
//用密钥初始化此密码  其中前一个参数表示加密(设置为:Cipher.DECRYPT_MODE就是解密) aesKey为密钥
cp.init(Cipher.ENCRYPT_MODE , aesKey);
//需要加密的字符串的字节数组
byte[] contenCode = text.getBytes("UTF-8");
//加密后得到的是字节数组
byte[] enCode = cp.doFinal(contenCode);

Java中AES算法的简单使用

简单使用

    /*
     * @description 加解密整合到一个方法中来
     * @author 三文鱼
     * @date 9:41 2022/3/18
     * @param rule 自己设置的密钥
     * @param text 需要加密的明文或者解密的密文
     * @param encrypt true表示加密 false表示解密
     * @return java.lang.String 返回加密或者解密过的字符串
     **/
    public static String getContrary(String rule , String text , boolean encrypt ) throws Exception {
        String result = "";
        try{
            //生成一个AES算法的密钥生成器
            KeyGenerator kg = KeyGenerator.getInstance("AES");
            //使用给定的随机源(可以看作你自己设置的密码,但对于程序而言,你输入的只是一个生成密钥的”种子“)
            // 初始化该密钥生成器(生成密钥长度为128位)
            kg.init(128, new SecureRandom(rule.getBytes("UTF-8")));
            //生成一个种子密钥。
            SecretKey ruleKey = kg.generateKey();
            //获取其主要编码格式的密钥
            byte[] skCode = ruleKey.getEncoded();
            //从给定的字节数组构造一个aes密钥
            SecretKey aesKey = new SecretKeySpec(skCode , "AES");
            //该类提供加密和解密的加密密码的功能。 它构成了Java加密扩展(JCE)框架的核心。
            Cipher cp = Cipher.getInstance("AES");
            //判断是否是加密
            if(encrypt) {
                //用密钥初始化
                cp.init(Cipher.ENCRYPT_MODE , aesKey);
                byte[] contenCode = text.getBytes("UTF-8");
                //加密
                byte[] enCode = cp.doFinal(contenCode);
                //按照base64编码
                result = new BASE64Encoder().encode(enCode);
            }else{
                cp.init(Cipher.DECRYPT_MODE , aesKey);
                //将密文按照base64解码
                byte[] enCode = new BASE64Decoder().decodeBuffer(text);
                //解密生成明文字节数组
                byte[] decryptCode = cp.doFinal(enCode);
                //明文字节数组生成明文
                result = new String(decryptCode , "UTF-8");
            }

            return result;
        }catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

参考资料

可厉害的土豆: AES加密过程详解| 对称加密| Rijndael-128| 密码学| 信息安全
我有一个小脑瓜 : 现代密码学|AES加密算法
百度百科: AES
百度文库: AES加密模式优缺点及用途

你可能感兴趣的:(Java加解密,算法)