实验原理
说明
P 代表明文,Pi 代表第 i 个明文分组,C 代表密文,Ci 代表第 i 个密文分组,K 代表密钥,IV 代表初始化向量。
1. AES 密码算法
AES 密码算法主要有四种运算,分别为字节替换,行移位,列混淆和轮密钥加;前面三种运算只处理明文,最后一个运算轮密钥加才和密钥进行运算,因为要解密所以这四种运算都是可逆的。10 轮的 AES 密码算法(AES128)过程如下图所示。

1.1 明文和密钥初始化
AES 中的运算都是以字节位单位的,128 位的明文可以分为 16 个字节,与一般的存储方式不同,这里的字节是**按列存储**的。密钥的初始化也与明文初始化相同,128 位的密钥分为 16 个字节**按列存储**,如下图所示。

1.2 字节替换和逆字节替换
本次实验不需要大家生成 S 盒,字节替换和逆字节替换的运算,只需要查找 S 盒和逆 S 盒中对应的元素作为输出即可。查找的方法为字节的**高 4 位作为行号**,低 4 位作为列号,对应 S 盒和逆 S 盒的元素则为需要替换的内容。以 95<->2a 为例 (16 进制表示), 如下图所示。


1.3 行移位和逆行移位
行移位是每行**按字节**移位(提醒大家注意,AES 算法中的处理都是以字节为单位的),第 1 行保持不变,第 2 行循环左移 1 个字节,第 3 行循环左移 2 个字节,第 4 行循环左移 3 个字节,完成行移位后每一列的四个字节被扩散到 4 个不同的列。逆行移位则与之相反,第 1 行保持不变,第 2 行循环右移 1 个字节,第 3 行循环右移 2 个字节,第 4 行循环右移 3 个字节。如下图所示。


1.4 列混淆和逆列混淆
列混淆的目的是以列为单位,使得输出的每 1 个字节和输入的 4 个字节都有关。具体运算就是左乘一个矩阵,其中的乘法运算为 GF(28) 上的乘法,模不可约多项式 m(x) 的乘法运算。列混淆和逆列混淆运算中的左乘矩阵互为逆。如下图所示。


1.5 轮密钥加
按字节将处理后的明文分组与当前轮次的密钥进行异或。它的逆也就是再异或一次轮密钥。

1.6 密钥扩展
由 4 个字(16 个字节)的种子密钥,生成一个 44 个字(1 个字 = 4 个字节 = 32 bits)的一维线性数组。初始化加上 10 次轮密钥加,每次用 4 个字。

具体扩展规则如下,初始密钥根据种子密钥按列存储;接下来根据 mod 4 的结果有两种处理方式,如下图所示。


2. 填充方式
2.1 NoPadding
不填充,明文的字节长度只能是 16 的整数倍,一般不适用。
2.2 Zeros
补 0,如果原数据字节长度恰好是 16 的倍数,也要补充多 16 个 0;
2.2 ISO10126
最后一个字节是填充的字节数(包括最后一个字节自己),其他全部填随机数。
示例 1:0123456789abc,0123456789abc 共 13 个字节,长度差 3,则会填充两个随机数(比如为 4 和 f)然后加上长度 3,0123456789abc4f3
示例 2:0123456789abcef0,长度刚好是 16 的整数倍,那就会再增加一个分组,前面 15 个位随机数,后面一个为长度 f,可能为 fe473564975fedgf
2.3 PKCS5 (PKCS7)
最后一组缺几个字节就填充几,如果刚好是 16 的整数倍,也要填充 16 个字节。
示例 1:0123456789abc共 13 个字节,再填充 3 个才够 16 个,PKCS7 填充时会在后面填充 3 个 3。填充后为0123456789abc333
示例 2: 0123456789abcef0,长度刚好是 16 的整数倍,那就会再增加一个分组为ffffffffffffffff
3. 工作模式
3.1【了解】电码本模式(ECB)
电码本模式(Electronic Codebook Book,简称 ECB):将明文按 16 个字节分组,每组分别加密后再拼接在一起就是加密后的明文。其缺点是如果分组的明文相同,那么对应的密文也将相同。因此常用于比较短的数据加密,比如密钥的加密。

说明
- Q: 最后一个分组是否需要填充?A: 是
- Q: 是否需要初始化向量?A: 否
3.2【深入了解,可动手完成】密文分组链接模式(CBC)
密文分组链接模式(Cipher Block Chaining, 简称 CBC):每一组明文先与初始化向量或者上一组的密文进行异或,得到的结果再与密钥进行加密。具体如下图所示。

说明
- Q: 最后一个分组是否需要填充?A: 是
- Q: 是否需要初始化向量?A: 是
3.3【了解】密文反馈模式(CFB)
密文反馈模式(Cipher FeedBack, 简称 CFB):在上面两个工作模式 ECB 和 CBC 中,整个数据分组需要在接收完之后才能进行加密。但是在一些网络应用中,需要即刻把一个终端输入的字符传给主机。这样上面的两种工作模式就不能满足。在 CFB 模式中,数据可以在比分组(8 bytes)小的单元里进行加密。其工作方式类似流密码。
CFB 模式中,假设传输的最小单元是 s(下图以 8bits 为例)位,分组大小为 b 位(AES 分组的大小是 128bits)。首先将初始化向量 IV 放到 b 位的移位寄存器中,加密函数输出最左边的 s 位,与明文分片 P1 进行异或,得到的密文 C1 并发送,然后把移位寄存器左移 s 位,把 C1 填入寄存器最右边的 s 位开始第二个明文分片的加密。具体如下图所示。

说明
- Q: 最后一个分组是否需要填充?A:否,类似流密码,不分组,因此不需要填充
- Q: 是否需要初始化向量?A:是
3.4【了解】输出反馈模式(OFB)
输出反馈模式(Output FeedBack, 简称 OFB):OFB 模式的结构跟上面 CFB 的模式很相似,不同的是它用加密函数的输出来填充移位寄存器,而 CFB 是用密文单元来填充移位寄存器。而且它是对这个分组来运算的。

说明
- Q:最后一个分组是否需要填充?A:否,如果最后分组只有
u位,u < b(b为分组长度),那么会将最后输出最左边的u位与最后分组的u位做异或运算,其余的b-u位舍弃。 - Q:是否需要初始化向量?A:是
3.5【可深入了解】计数器模式(CTR)
计数器模式(Counter, 简称 CTR):计数器模式使用与明文文组规模相同的长度,第一个明文分组与加密后的初始的计数器进行异或,后面随着消息块的增加计数器的值加 1。

说明
- Q: 最后一个分组是否需要填充? A:否,如果最后分组只有
u位,u < b(b为分组长度),那么会将最后输出最左边的u位与最后分组的u位做异或运算,其余的b-u位舍弃。 - Q: 是否需要初始化向量? A:是