Advanced Encryption Standard

(高级加密标准)

性质

对称加密,块加密,流加密
密钥长度固定为:128,192,256bit
加密模式分为:CBC,CFB,OFB,CTR,GCM,ECB

  • 对称加密:加密密钥和解密密钥相同

分组密码和流密码

分组密码是每次只能处理特定长度的一块数据的一类密码算法,这里的“一块”就称为分组。一个分组的比特数就称为分组长度。
流密码是对数据流进行连续处理的一类密码算法。流密码一般以1比特、8比特或32比特等为单位进行加密和解密。
分组密码算法只能加密固定长度的分组,但需要加密的明文长度可能会超过分组密码的分组长度,这就需要对分组密码算法进行迭代,以便将一段很长的明文全部加密。迭代的方法就被称为分组密码的模式。

  • ECB模式:Electronic CodeBook mode(电子密码本模式)
  • CBC模式:Cipher Block Chaining mode(密码分组链接模式)
  • CFB模式:Cipher FeedBack mode(密文反馈模式)
  • OFB模式:Output FeedBack mode(输出反馈模式)
  • CTR模式:CounTeR mode(计数器模式)
模式 名称 优点 缺点 备注
ECB模式 Electronic CodeBook mode(电子密码本模式) 简单、快速、支持并行运算(加密、解密) 明文中的重复排列会反映在密文中;通过删除、替换密文分组可以对明文进行操作;对包含某些比特错误的密文进行解密时,对应的分组会出错;不能低于重放攻击。 不应使用
CBC模式 Cipher Block Chaining mode(密码分组链接模式) 明文的重复排列不会反映在密文中;支持并行计算(仅解密);能够解密任何密文分组 对包含某些错误比特的密文进行解密时,第一个分组的全部比特以及后一个分组的相应比特会出错;加密不支持并行计算 CRYPTREC推荐;《实用密码学》推荐
CFB模式 Cipher FeedBack mode(密文反馈模式) 不需要填充(padding);支持并行计算(仅解密);能够解密任意密文分组 加密不支持并行计算;对包含某些错误比特的密文进行解密时,第一个分组的全部比特以及后一个分组的相应比特会出错;不能低于重放攻击 CRYPTREC推荐
OFB模式 Output FeedBack mode(输出反馈模式) 不需要填充(padding);可实现进行加密、解密的准备;解密解密使用相同结构;对包含某些错误比特密文解密时,只有明文中相应的比特会出错 不支持并行计算;主动攻击者反转密文分组中的某些比特时,明文分组中相应的比特也会被反转 CRYPTREC推荐
CTR模式 CounTeR mode(计数器模式) 不需要填充(padding);可实现进行加密、解密的准备;解密解密使用相同结构;对包含某些错误比特密文解密时,只有明文中相应的比特会出错;支持并行计算(加密、解密) 主动攻击者反转密文分组中的某些比特时,明文分组中相应的比特也会被反转 CRYPTREC推荐;《实用密码学》推荐

以上内容来自(分组密码的模式——ECB、CBC、CFB、OFB、CTR_ofb是指分组密码的哪种工作模式-CSDN博客)


过程

明文分块

把所有明文分为n块,每块128bit。如果最后不足,需要填充:

  • NoPadding: 不做任何填充,但是要求明文必须是16字节的整数倍。
    PKCS5Padding(默认): 如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。 比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6 }
    ISO10126Padding:如果明文块少于16个字节(128bit),在明文块末尾补足相应数量的字节,最后一个字符值等于缺少的字符数,其他字符填充随机数。比如明文:{1,2,3,4,5,a,b,c,d,e},缺少6个字节,则可能补全为{1,2,3,4,5,a,b,c,d,e,5,c,3,G,$,6}
    PKCS7Padding原理与PKCS5Padding相似,区别是PKCS5Paddingblocksize为8字节,而PKCS7Paddingblocksize可以为1到255字节
  • 需要注意的是,如果在AES加密的时候使用了某一种填充方式,解密的时候也必须采用同样的填充方式。

然后每一块按序排列成4x4矩阵

S盒生成

img

这个表是S盒,生成方法如下:

  1. 对S盒初始化为00,01,02,03,…,FE,FF
  2. 用每一格的乘法逆元代替这一格,域是$GF(2^8)$
  3. 对每一格的bit位进行运算,令$b_i^,=b_i\oplus b_{i+4 mod 8}\oplus b_{i+5 mod 8}\oplus b_{i+6 mod 8}\oplus b_{i+7 mod 8}\oplus c_i$,其中$c = {01100011}$

逆S盒:用于解密

字节替代

通过每一字节前4位和后四位分别作为S盒的行标和列标,替换为对应位置的值

行移位

把上面已经分为4x4的矩阵中,第i行左移i位

列混淆

最矩阵经行矩阵乘法:
$$
\begin{bmatrix}
2 & 3 & 1 & 1 \\
1 & 2 & 3 & 1 \\
1 & 1 & 2 & 3 \\
3 & 1 & 1 & 2
\end{bmatrix} \tag{1}
*
before = after
$$

轮密钥加

每一轮输入与轮密钥进行异或,该项一定出现在加密的首尾,保证安全性

轮密钥的生成是初始密钥和该轮子密钥异或的结果

密钥扩展

密钥扩展用于生成子密钥

现在假设已经有初始密钥的4x4矩阵

对它分列(以列为单位分成4个)为$W_0,W_1,W_2,W_3$。那么扩展密钥就是扩展出$W_4,W_5,W_6……$

具体公式是:
$$
\begin{equation}
\left{
\begin{aligned}
W_i & = W_{i-4} \oplus W_{i-1} \\
W_i & = W_{i-4} \oplus T({W_{i-1}})
\end{aligned}
\right.
\end{equation}
$$
其中T是函数其作用是:

  1. 假设输入的是$W_i$
  2. 对这一列循环左移一位(列移位),对于$W_i$这一列,就是上移一位
  3. 用S盒对2之后的$W_i$进行字节替代,规则同加密的字节替代
  4. 与给定的矩阵进行异或,矩阵是[RC[j],0,0,0]轮常量是RC = {01, 02, 04, 08, 10, 20, 40, 80, 1B, 36}.j是该轮轮数

然后每4列作为一组成为轮密钥

补充

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

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

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

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

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

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

(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-8] xor temp;/*将上一个字(处理或没处理过)
与6个字之前的字进行异或,得到当前的字*/
}
}

此段摘自zhuanlan.zhihu.com/p/360393988

总过程

加密时,执行:

  • 轮密钥加
  • (字节替代+行位移+列混淆+轮密钥加)*9
  • 字节替代+行位移+轮密钥加

以上过程是对于16字节密钥的