加解密模式分析 - AES 加密算法
AES(Advanced Encryption Standard)是当前最广泛使用的对称分组加密算法,由美国国家标准与技术研究院(NIST)于 2001 年正式发布。AES 以其卓越的安全性和高效的性能,成为现代加密协议中的核心组件,广泛应用于 TLS、IPsec、Wi-Fi 等众多安全通信协议中。
在本章中,我们将深入剖析 AES 加密算法的核心原理与实现细节。我们将从分组密码的基础特性出发,逐步拆解 AES 的 10、12 或 14 轮加密过程,详细分析其状态矩阵的构造、每轮的操作步骤(SubBytes、ShiftRows、MixColumns、AddRoundKey)以及最终的密钥扩展机制,全面理解 AES 的加密过程和安全性分析。
AES 加密算法 🫡
AES 块长度为 128 位,密钥长度可以是 128 位、192 位或 256 位,分别对应 10、12 或 14 轮加密过程,明文按照 128 位分组,加密得到 128 位密文。
AES 算法不同于 DES 的 Feistel 结构,而是采用了 Substitution-Permutation Network(SPN)结构,直接使用四个 “算法层” 对整个数据块进行变换。
密钥扩展(Key Expansion)
标准的 128 位 AES 密钥对应由 11 组子密钥,分别在一开始和每一轮参与密钥加法层的运算。
子密钥的生成是一列为单位的,一列是 4 字节(32 位),每一轮需要 4 列(128 位)的子密钥。对于 128 位密钥,原始密钥占用前 4 列,后续的 7 组子密钥通过迭代计算得到,储存在 $w[0..43]$ 的子密钥数组中。
具体来说,子密钥的生成过程如下:
- 将原始密钥分成 4 列,每列 4 字节,填充到子密钥数组的前 4 列。
- 从第 5 列开始,依次计算每一列的子密钥:
- 如果当前列索引 $i$ 是 4 的倍数,则进行 G 函数特殊处理,然后将前一列的子密钥与当前列的前一列的子密钥进行异或运算。
- 否则,直接将前一列的子密钥与当前列的前一列的子密钥进行异或运算。

G 函数是为了增加密钥扩展的非线性和消除 AES 中的对称性(轮常量的参与),进行如下操作:
- 将输入的 4 字节进行循环左移(RotWord),即将第一个字节移到最后。
- 将每个字节通过 S 盒进行字节替代(SubWord),得到一个新的 4 字节。
- 将第一个字节与一个轮常量(Rcon)进行异或运算,得到最终的 4 字节输出。

@staticmethod
defkey_expansion(k,r):
#fips-197 Figure 11
k = list(k) # in case k is bytes
Nk = len(k) // 4
subkeys=[k[i:i+4]foriinrange(0,4*Nk,4*Nk,4)]
i = Nk
while i < 4*(r+1):
t=subkeys[i-1]
if i % Nk == 0:
tt=AES.sub_word(AES.rot_word(t))
t=[tt[0] ^AES.Rcon[i // Nk]] + tt[1:]
elif Nk > 6 and i % Nk == 4:
t = AES.sub_word(t)
subkeys.append(AES.word_xor(subkeys[i - Nk], t))
i += 1
return subkeys
密钥加密层(Key Additon Layer)
AES 的内部状态是由一个 4x4 的字节矩阵(State)构成的,每个元素是一个字节(8 位)。输入的 16 字节按照如下方式排列:
将排列好的明文和子密钥逐字节异或,并将结果输出:
@staticmethod
def add_round_key(s, k):
for i in range(16):
s[i] ^= k[i]
字节替代层(Substitution Layer)
让输入的每一个字节,通过 S 盒代换(映射)到另外一个字节此处的 S 盒是可以经过每种方式计算出来的,也可以直接使用计算好的进行代换。这个比较基础,我就不展开了。
@staticmethod
def sub_bytes(s):
for i in range(16):
s[i] = AES.Sbox[s[i]]
扩散层(Diffusion Layer)
扩散层包括行移位层(Shift Rows层)和列混淆层(Mix Column层)。行位移和列混淆都是 AES 的混淆层,目的是为了将单个字节的变换扩散到整个状态矩阵中,增加算法的安全性。
行移位层:对于 4x4 的矩阵,在做行移位时,第一行保持不变,第二行往左移动一格,第三行左移两格,第四行左移三格。
列混淆层:将整个字节矩阵乘上一个列混淆矩阵(有限域上的矩阵运算),相当于正常矩阵运算结果取模。
@staticmethod
def shift_rows(s):
s[i] = list(s[0::5] + s[4::5] + s[3:4:5] + s[8::5] + s[2:8:5] +s[12::5] + s[1:12:5])
@staticmethod
def mix_columns(s):
def xtime(a):
return((((a << 1) ^ 0x1B) & 0XFF) if (a & 0x80) else (a <<1))
for i in range(4):
t=s[4*i] s[4*i+1] ^s[4*i+2]^s[4*i+3]
u=s[4*i]
s[4*i] ^=t xtime(s[4*i] ^ s[4*i+1])
s[4*i+1] ^= t xtime(s[4*i+1] ^ s[4*i+2])
s[4*i+2] ^= t xtime(s[4*i+2] ^ s[4*i+3])
s[4*i+3] ~ t xtime(s[4*i+3] ^ u)
轮加密过程
这里就是一开始的示意图了,不过要注意的是最后一轮没有 Mix Column 层。
# start
r=0
k_sch=self.subkeys[0] + self.subkeys[1] + self.subkeys[2] + self.subkeys[3]
state = list(msg)
AES.add_round_key(state,k_sch)
# round 1~rounds'-1
for r in range(1,self.rounds):
AES.sub_bytes(state)
AES.shift_rows(state)
AES.mix_columns(state)
k_sch=self.subkeys[4*r] + self.subkeys[4*r+1] + self.subkeys[4*r+2] + self.subkeys[4*r+3]
AES.add_round_key(state,k_sch)
# the last round
r = self.rounds
AES.sub_bytes(state)
AES.shift_rows(state)
k_sch=self.subkeys[-4] + self.subkeys[-3] +self.subkeys[-2] + self.subkeys[-1]
AES.add_round_key(state,k_sch)
# convert 'list'stateto'bytes'output
output=bytes(state)
return output
AES 加解密 😆
AES 的加密和解密过程非常相似,主要区别在于解密过程中需要使用逆向的操作顺序和逆向的 S 盒、逆向的行移位以及逆向的列混淆。由于 AES 是一个 SPN 结构的算法,解密过程需要对每一轮的操作进行逆向处理,这里就不展开了,感兴趣的同学可以参考 AES 的官方文档或者相关的加密算法教材。
# 我们可以使用 Python 的 Crypto 库来实现 AES 的加密和解密,以下是一个简单的示例:
from Crypto.Cipher import AES
key = b""
aes = AES.new(key,mode=AES.MODE_ECB)
plaintext = b""
ciphertext = aes.encrypt(plaintext)
aes.decrypt(ciphertext)
上一章:加解密模式分析 - DES 加密算法 👈
下一章:加解密模式分析 - 分组模式解析 👈
回到开始:关于我 👈
相关链接:








