【密码学】(二)高级加密标准(AES)

  • ~5.64K 字
  1. 1. 一、AES的整体结构及简介:
  2. 2. 二、AES的迭代函数:
    1. 2.1. 1.字节代替(作用为混淆):
    2. 2.2. 2.行移位(作用为扩散):
    3. 2.3. 3.列混合(作用为扩散):
    4. 2.4. 4.轮密钥加:
  3. 3. 三、AES的密钥编排算法

本文转载自:《现代密码学》课程笔记知乎专栏
仅作个人学习记录。

上一次讲了分组密码的基本概念和DES

总结如下:

图5-1 上一讲总结

一、AES的整体结构及简介:

1.AES简介:

AES即高级加密标准(Advanced Encryption Standard),是美国NIST在2001年发布的,旨在代替DES称为广泛使用的标准。AES是一种对称分组密码算法。

2.AES的分组长度和密钥长度:

AES的明文分组长度为128位(16字节),密钥长度可以为128位(16字节)、192位(24字节)、256位(32字节),根据密钥长度的不同,AES分为AES-128、AES-192、AES-256三种。

3.AES的整体结构:

AES加密体制也是由多轮加密构成,除了结尾的一轮,其他轮都是由四个步骤组成——字节代替、行移位、列混淆、轮密钥加。而最后一轮仅包括字节代替、行移位、轮密钥加这三步。AES迭代的轮数与密钥的长度相关,16字节的密钥对应着迭代10轮,24字节的密钥对应着迭代12轮,32字节的密钥对应着迭代14轮。在开始所有轮迭代之前,需要进行一次初始变换——一次轮密钥加,这一步往往被称为第0轮。

图5-2和图5-3是对AES结构的简单描述:

图5-2 AES加密过程

我们知道DES的加解密结构是完全相同的,但是AES的加解密结构却不同,这是因为AES没有采用Feistel密码体制。但是AES每一个步骤都是可逆的,因此只要把AES加密中的每一步换成其逆变换,即可得到AES解密算法。值得注意的是,解密算法也是先进行第0轮,而且最后一轮也是只有三步。在解密算法中,需要倒着顺序使用轮密钥。

图5-3 AES加密和解密过程(详细)

二、AES的迭代函数:

上一部分提到,AES需要依次执行十几次迭代。这一部分,我们来讲一讲每一轮迭代四个步骤:字节代替、行移位、列混淆、轮密钥加的细节。

与DES不同,AES的每一步都有其设计的具体原理,我们在这里也会详细讲解。

1.字节代替(作用为混淆):

(1)实现方法:

字节代替就是一个简单的查表操作。具体做法就是对明文的每一个字节使用S盒进行查表代替(AES明文共16字节,128位)。

S盒如下图所示:

图5-4 AES的S盒

明文的一个字节由8位组成,以这8位的高4位作为S盒表的行值低4位作为S盒表的列值。在其中寻找对应的代替结果。例如:十六进制数{3F}表示代替结果在第三行,第F列,因此结果为{75}。

同样,在执行解密过程时,需要经过逆字节代替,因此也有相应的逆S盒,其代替方法与S盒完全相同。逆S盒与S盒是互逆的。

逆S盒如下图所示:

图5-5 AES的逆S盒

(2)设计原理:

以下讲解S盒是怎么被设计成这个样子的:

  • 首先,对16x16格的S盒进行升序初始化:按照行列值,一直从{00},递增初始化到{FF}。比如:第一行:{00},{01},{02},{03}……{0F};第二行:{10},{11}……{1F}。
  • 经过初始化后,分别用S盒每一格的乘法逆元( 中的)代替原来格子中的内容,{00}仍然用{00}代替。
  • S盒的每一格均为8位,把这8位分别记为 。之后,分别对S盒的每一格进行如下变换:

图5-6 S盒的构造

其中, 表示更新后的位值,

用矩阵表示为

图5-7 矩阵表示

这里的矩阵乘法与线性代数中的完全相同,只是乘或加之后需要

这个矩阵变换可以被表示为 ,由此可以看出,这个矩阵变换存在逆变换 。由此式可以构造逆字节代替变换。

2.行移位(作用为扩散):

实现方法非常的简单。AES的明文分组长度为128位,共16个字节。首先将这16个字节按顺序排成一个 的方阵(每行4个字节,共4行)。之后,方阵的第一行不变;方阵的第二行循环左移一个字节;方阵的第三行循环左移两个字节;方阵的第四行循环左移三个字节。注意:加密以字节为单位,如下图所示:

图5-8 行移位举例

逆向行移位的实现方式与正向相同,只是改成了循环右移。

3.列混合(作用为扩散):

首先,把16字节的待加密明文以字节为单位按顺序排列成 的方阵(与行移位排列方式相同)。之后,这个字节方阵的每一列都可以表示为一个系数在域上的次数小于4的多项式**,共4个多项式,分别为 。列混合就是执行以下过程:

其中 ,{}代表16进制数。

这个过程也可以写为矩阵形式:

让待加密的 字节方阵乘以一个矩阵,得出的结果就是列混合后的字节方阵。其中所有的乘法和加法均为 上的乘法和加法,分别用 表示。

如下图所示:等号左边,右侧的矩阵为待列混合的字节方阵,左侧为相乘的矩阵,等号右侧为结果。这个过程也可以拿矩阵下面的等式来表示。

图5-9 列混合矩阵形式

逆向列混合对应的矩阵变换为:

图5-10 逆向列混合

显然,可以证得,这两个矩阵是互逆的:

图5-11 两矩阵互逆

4.轮密钥加:

轮密钥是原来的密钥经过密钥编排算法得到的一个密钥,其长度与明文分组长度相同——16字节、128位,AES中,每一轮迭代的轮密钥都互不相同,之后会详细讲解密钥编排算法。

所谓轮密钥加,就是简单地将待加密的内容与轮密钥按位异或。也可以视为字节之间的操作,如下图所示:左边是待加密的内容,右边是轮密钥,等号右边为结果。

图5-12 轮密钥加举例

轮密钥加的逆变换与正向变换相同,即密文再次与轮密钥进行按位异或即得到原来的内容。

三、AES的密钥编排算法

AES的密钥长度可以为16字节,24字节或者32字节,根据密钥长度的不同,AES分为AES-128、AES-192、AES-256三种。这里常以字(word)为单位来衡量密钥长度, ,因此AES的密钥长度可以为4字、6字或者8字

AES的密钥编排算法包含密钥扩展轮密钥选取两部分。密钥扩展用来将原来的4字、6字或者8字密钥扩展成拥有一定字数的长密钥;轮密钥选取用来从长密钥中选取若干部分,使其充当AES每一轮迭代的轮密钥。

1.密钥扩展算法:

(1)为什么需要密钥扩展:

不论密钥长度为多少,我们的明文分组始终为16字节(4字)。上文提到,在轮密钥加部分,我们需要为每一轮提供一个长度为4字的轮密钥。

对于AES-128(4字密钥),需要迭代10轮,加上第0轮,共需要进行11次轮密钥加,而每一次轮密钥加都需要一个长度为4字的轮密钥,因此所需要的扩展密钥长度为 字。

对于AES-192(6字密钥),需要迭代12轮,加上第0轮,共需要进行13次轮密钥加,所需要的扩展密钥长度为 字。

对于AES-256(8字密钥),需要迭代14轮,加上第0轮,共需要进行15次轮密钥加,所需要的扩展密钥长度为 字。

因此我们需要一定的方法用来将密钥扩展到一定的长度。

(2)AES-128的密钥扩展方法:

在这个算法中,输入的原密钥长度为16字节(byte),保存在数组key[16]中,输出为长为44字(word)的扩展密钥,保存在数组w[44]中。

其扩展算法可用下面的伪代码描述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//只是伪代码,不能运行
KeyExpansion(byte key[16], word w[44])
{
word temp;
for(int i = 0; i < 4; i++)//第一个for循环,填充w的前4个字
w[i] = {key[4*i], key[4*i+1],
key[4*i+2], key[4*i+3]};
for(int i = 4; i < 44; i++)//第二个for循环,填充后面的内容
{
temp = w[i-1];//保存上一个字
if (i % 4 == 0)//如果整除4
temp = SubWord (RotWord (temp))
xor Rcon[i/4];//对保存的上一个字进行复杂的处理
w[i] = w[i-4] xor temp;/*将上一个字(处理或没处理过)
与4个字之前的字进行异或,得到当前的字*/
}
}
  • 第一个for循环:首先直接把输入密钥的4个字复制到扩展密钥的前4个字上。
  • 第二个for循环:对扩展密钥的后40个字进行处理,处理的步骤如下:

(a).使用temp变量保存前一个字的内容

(b).如果当前密钥字的编号(从0开始数)能够整除4,就对temp先后进行字循环(RotWord)字代替(SubWord)两个变换,之后再进行轮常量异或(这三步一般统称为函数g)。如果当前密钥字的编号(从0开始数)不能够整除4,则跳过这一步,直接进入步骤f。

(c).字循环(RotWord):将一个字中四个字节的内容循环左移一个字节。即使得 变为

(d).字代替(SubWord):使用前面提到的S盒(图5-4)对一个字中的每一个字节进行代替。

(e).轮常量异或:经过步骤c、d后,所得的结果再与轮常量Rcon[i/4]进行按位异或,即得到最终的temp。这里的 ,即其右边三个字节总为0,左边第一个字节取决于 。这里 定义在 上),且 。可以发现,轮常量与迭代的第几轮有关,AES-128有10个轮常量,如下表所示:

图5-13 10个轮常量

(f).使用4个字之前的字与temp(如果没有经过处理,则为上一个字)进行异或,即得到当前字。

总结规律,我们可以看出,除了第0轮的轮密钥,其他轮的当前字都是由前一个字(可能经过函数g处理,也可能没经过)与4个字之前的字进行异或得到。此外,每一个轮密钥的最后一个字总要经过函数g(字循环、字代替、轮常量异或)的作用。

图5-14 密钥扩展算法的简明表示

(2)AES-192的密钥扩展方法:

AES-192的密钥有6个字,其密钥扩展方法与AES-128完全类似。第一个for循环的填充变成了6个字;之后的判断整除条件变为了能否整除6。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//只是伪代码,不能运行
KeyExpansion(byte key[24], word w[52])
{
word temp;
for(int i = 0; i < 6; i++)//第一个for循环,填充w的前6个字
w[i] = {key[4*i], key[4*i+1],
key[4*i+2], key[4*i+3]};
for(int i = 6; i < 52; i++)//第二个for循环,填充后面的内容
{
temp = w[i-1];//保存上一个字
if (i % 6 == 0)//如果整除6
temp = SubWord (RotWord (temp))
xor Rcon[i/6];//对保存的上一个字进行复杂的处理
w[i] = w[i-6] xor temp;/*将上一个字(处理或没处理过)
与6个字之前的字进行异或,得到当前的字*/
}
}

(3)AES-256的密钥扩展方法:

AES-256的密钥长度为8字。其密钥扩展与AES-128也基本相同,只是修改了填充的字数,值得注意的是:AES-256在第二个for循环里添加了判断条件,当i%==4时,要对temp进行一次字代替。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//只是伪代码,不能运行
KeyExpansion(byte key[32], word w[60])
{
word temp;
for(int i = 0; i < 8; i++)//第一个for循环,填充w的前8个字
w[i] = {key[4*i], key[4*i+1],
key[4*i+2], key[4*i+3]};
for(int i = 8; i < 60; i++)//第二个for循环,填充后面的内容
{
temp = w[i-1];//保存上一个字
if (i % 8 == 0)//如果整除8
temp = SubWord (RotWord (temp))
xor Rcon[i/8];//对保存的上一个字进行复杂的处理
else if(i % 8 == 4)//如果除8余4
temp = SubWord (temp);
w[i] = w[i-6] xor temp;/*将上一个字(处理或没处理过)
与6个字之前的字进行异或,得到当前的字*/
}
}

2.轮密钥选取算法:

经过密钥扩展算法,我们得到了一长串扩展密钥,现在需要将扩展密钥分为一系列的轮密钥,从而应用到轮密钥加步骤中。

选取方法就是简单地按先后顺序选取,依次充当各轮的轮密钥,如下图所示:

图5-15 AES-128轮密钥选取

图5-16 AES-192轮密钥选取

图5-17 AES-256轮密钥选取

这就是AES的全部内容。