想象你开了一家“明码果汁铺”,顾客点单时,你不想让隔壁老王偷看配方。于是你买了一台“魔法搅拌机”:把一盒水果丁(明文)放进去,按照一本被全世界公开的菜谱(算法)搅拌 10 遍——换皮、重排、混匀、加料,最终榨出一杯任何人都看不懂的密文果汁。但奇妙的是,只要握有一瓶秘制底料(密钥),这台搅拌机就能一键倒放,把果汁还原成原来的水果丁。这台搅拌机,就是 AES(Advanced Encryption Standard,高级加密标准)。 从你手机里的 HTTPS 网页,到银行转账、WiFi 密码,AES 每天都在默默保护着几十亿人的数据。这篇文章不堆砌公式,而是带你以“果汁铺老板”的视角,把 AES 的每一道工序拆开看一遍。你会明白:为什么换皮、重排、混匀、加料这四招反复用 10 轮,就能让最顶尖的黑客也束手无策。

岗位关联

掌握 AES 原理是安全工程师、密码工程开发者的基本功。理解分组结构、轮函数与工作模式,能帮你在系统架构中正确选择加密方案,避免因配置错误导致数据泄露。

目录
  1. 可视化演示
  2. 1. AES概述:魔法搅拌机的身世
  3. 2. 整体框架:把水果丁码进冰格
  4. 3. SubBytes:给每颗水果换一张皮
  5. 4. ShiftRows:把冰格的行错位推一推
  6. 5. MixColumns:把四杯果汁倒一起打匀
  7. 6. AddRoundKey:撒入这一轮的神秘调料
  8. 7. 密钥扩展:一瓶底料兑出十种腌料
  9. 8. 工作模式:一盒水果丁怎么分批榨
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

AES是美国标准对称加密算法,采用分组密码与多轮替换置换结构。本文详解AES的分组结构、SubBytes字节替... 切换模式查看不同维度。

本节配有交互动效(进入视口后自动加载,约 3KB)。

AES分组加:核心原理 动态展示关键流程与数据流动 交互控件调节参数实时渲染 f(x) = transform(x) 核心概念的可视化呈现

1. AES概述:魔法搅拌机的身世

你的果汁铺开业后生意火爆,可问题是:市面上有几十种“搅拌机”,有的水果丁越搅越碎却能被轻松还原,有的机器本身就有后门。于是你决定认准一款由美国国家标准与技术研究院(NIST)在 2001 年公开海选出的冠军机型——Rijndael,官方命名为 AES。它的最大特点是:菜谱完全公开,全世界密码学家围观了二十年都没找出漏洞;而安全的关键,全在那瓶只有你有的秘制底料(密钥)上。

AES 属于分组密码(block cipher):它一次只处理固定长度的一盒水果丁——128 位,也就是 16 个字节。如果明文很长,就切成很多个 16 字节小块,一块一块放进搅拌机。同时它是对称加密:榨汁(加密)和还原(解密)用的是同一把钥匙。这就像你店里的配方锁箱——同一个密码既能锁上也能打开,简单高效,适合大量数据。

AES 支持三种规格的密钥:128 位、192 位、256 位。密钥越长,搅拌机内部设计的“轮数”就越多,暴力破解的难度也指数级上升。但别误会,不是钥匙越长就一定更好——128 位在现代算力下已经足够安全,256 位更多是为了应对未来量子计算机的威胁。

2. 整体框架:把水果丁码进冰格

开工前,你得先把 16 个字节的明文“码”进一只 4×4 的冰格里,密码学里叫状态矩阵(State)。第 0 个字节放第 0 行第 0 列,第 1 个字节放第 1 行第 0 列……按列填满。为什么用矩阵而不是一长条?因为后面四道工序——换皮、重排、混匀、加料——全都要基于“行”和“列”来操作。

整体流程像一份标准 sOP。先做一次“加料”(AddRoundKey)作为前奏,然后进入主循环:SubBytes → ShiftRows → MixColumns → AddRoundKey,这四步合称轮函数。每一轮结束后,矩阵里的每个字节都已经被其他字节“影响”过,这就是密码学追求的雪崩效应——哪怕只改一个比特,密文也会面目全非。

轮数由密钥长度决定:

其中 $N_k$ 是密钥的“字数”(每字 32 位:128 位密钥 $N_k=4$,192 位 $N_k=6$,256 位 $N_k=8$),$N_b=4$ 是状态矩阵的列数。

所以你手里的 128 位密钥,对应 10 轮搅拌。整体框架理解之后,我们逐一走进每一道工序。

Nr=6+max⁡(Nk,Nb)N_r = 6 + \max(N_k, N_b)
  1. 求密钥字数 Nk把密钥长度除以 32。例如 128 位密钥得到 $N_k = 128 / 32 = 4$。
    Nk=密钥位数32N_k = \frac{密钥位数}{32}
  2. 取最大值$\max(N_k, N_b)$ 表示在密钥字数和分组列数里取较大的一个,AES 中 $N_b$ 恒为 4。
    max⁡(4,4)=4\max(4, 4) = 4
  3. 加上固定偏移 6这是 AES 设计者通过安全分析确定的“最低安全轮数”。
    Nr=6+4=10N_r = 6 + 4 = 10

3. SubBytes:给每颗水果换一张皮

第一道工序叫字节替换,AES 里写作 SubBytes。这一步做什么?把状态矩阵里的每一个字节,通过一张名叫 S 盒(S-box) 的 256 格查表,换成另一个完全不同的字节。就像你给每一颗水果丁换皮:苹果变橙子,橙子变猕猴桃,猕猴桃变火龙果——皮相全变,但“这个位置有一颗粒子”的事实没变。

这一步的关键词是非线性。如果所有工序都是“线性”的(像乘一个数、加一个数),那攻击者就能列出一堆线性方程,用代数方法直接解出密钥。而 S 盒就像一张没有规律的“魔术贴纸”,让输入和输出之间不存在简单的数学关系,把线性攻击的路彻底堵死。

这一步想说明白:换皮只是“一对一换妆”,位置没动。真正让信息开始“串门”的,是下一道工序。

Si,j′=Sbox[Si,j]S'_{i,j} = \mathrm{Sbox}\bigl[S_{i,j}\bigr]
  1. 定位字节 $S_{i,j}$先取出状态矩阵中第 $i$ 行第 $j$ 列的那个字节,它是一个 0 到 255 之间的数字。
    Si,j∈{0,1,…,255}S_{i,j} \in \{0, 1, \ldots, 255\}
  2. 查 S 盒把这个数字当作 S 盒的行列索引,查出新字节并写回同一位置。
    Si,j′=Sbox[Si,j]S'_{i,j} = \mathrm{Sbox}[S_{i,j}]

4. ShiftRows:把冰格的行错位推一推

第二道工序叫行移位(ShiftRows)。请想象你把冰格端起来,把每一行像推麻将牌一样向左错开:第一行不动,第二行向左推 1 格,第三行向左推 2 格,第四行向左推 3 格。被推出去的水果丁从左边冒出来,绕回右边补位。这样一来,原本竖着排成一列的 4 个字节,就被打散到了四个不同的列里。

为什么要这么做?因为下一步 MixColumns 是按“列”混合的。如果列里的字节都是同一列的“老熟人”,攻击者可以逐列破解;而 ShiftRows 让每一列都凑齐来自四行的“陌生人”,为列混淆提供跨行扩散的素材。

解密时方向相反,每行向右移回去即可,完美可逆。

Sr,c′=Sr, (c+r) mod 4S'_{r,c} = S_{r,\, (c+r) \bmod 4}
  1. 确定行号 r$r=0$ 的行不动,$r=1$ 左移 1 格,$r=2$ 左移 2 格,$r=3$ 左移 3 格。
    r∈{0,1,2,3}r \in \{0,1,2,3\}
  2. 计算新列号 $(c+r) \bmod 4$把原列号加上行号,再对 4 取模,实现循环回绕。
    c′=(c+r) mod 4c' = (c + r) \bmod 4

5. MixColumns:把四杯果汁倒一起打匀

第三道工序列混淆(MixColumns)是四道工序里最“数学”的一步。规则是:取出状态矩阵的每一列(4 个字节),让它与一个固定的 4×4 矩阵相乘,得到一列新的 4 字节。这里的乘法和加法不是普通算术,而是伽罗瓦域 $GF(2^8)$ 里的运算——你可以把它想象成一种特殊的“螺旋搅拌规则”,保证结果仍然落在 0~255 之间。

效果上,列混淆就是“充分混匀”:原来一列里某一个字节的任何细微变化,经过混合后会扩散到这一列的全部 4 个字节中。ShiftRows 已经让每列凑齐了四个方向的字节,MixColumns 再让它们彼此“串味”——这就是 AES 扩散性的核心来源。

注意最后一行的公式里 $2S$ 表示 $GF(2^8)$ 乘法,不是普通乘法。解密时使用另一张“逆向矩阵”即可还原。

[S0,c′S1,c′S2,c′S3,c′]=[2311123111233112][S0,cS1,cS2,cS3,c]\begin{bmatrix} S'_{0,c} \\ S'_{1,c} \\ S'_{2,c} \\ S'_{3,c} \end{bmatrix}=\begin{bmatrix} 2 & 3 & 1 & 1 \\ 1 & 2 & 3 & 1 \\ 1 & 1 & 2 & 3 \\ 3 & 1 & 1 & 2 \end{bmatrix}\begin{bmatrix} S_{0,c} \\ S_{1,c} \\ S_{2,c} \\ S_{3,c} \end{bmatrix}
  1. 取出第 c 列四个字节把状态矩阵第 $c$ 列的 $S_{0,c}, S_{1,c}, S_{2,c}, S_{3,c}$ 当作列向量。
    v=(S0,c,S1,c,S2,c,S3,c)T\mathbf{v} = (S_{0,c}, S_{1,c}, S_{2,c}, S_{3,c})^{\mathsf{T}}
  2. 乘以固定矩阵用设计好的 4×4 矩阵去乘这个列向量,矩阵里的 2、3、1 是 $GF(2^8)$ 中的常数。
    v′=M⋅v\mathbf{v}' = M \cdot \mathbf{v}
  3. 每行结果写回把新向量的 4 个分量写回第 $c$ 列,完成一列混合。
    Si,c′=2Si,c⊕3Si+1,c⊕Si+2,c⊕Si+3,cS'_{i,c} = 2S_{i,c} \oplus 3S_{i+1,c} \oplus S_{i+2,c} \oplus S_{i+3,c}

6. AddRoundKey:撒入这一轮的神秘调料

最后一道工序轮密钥加(AddRoundKey),是把状态矩阵与这一轮专属的 16 字节轮密钥做按位异或(XOR)。异或的规则很直白:两个比特相同得 0,不同得 1。这就像在果汁里撒入这一轮的秘制调料——调料配方(轮密钥)来自你那瓶底料,搅拌机每转一轮就换一种调料。

异或有一个绝妙性质:自己异或自己等于 0。所以在解密时,只要把同样的轮密钥再异或一次,状态就原样恢复了。这保证了 AES 解密流程可以精准“倒放”,而不需要发明另一套运算。

到这里,一轮搅拌完成。但一个关键问题出现了:每一轮的“调料”从哪来? 不可能 10 轮都用同一把钥匙——那样攻击者只需要猜一次钥匙就够了。

Si,j′=Si,j⊕Ki,jrS'_{i,j} = S_{i,j} \oplus K^r_{i,j}
  1. 取状态字节 $S_{i,j}$ 与轮密钥字节 $K^r_{i,j}$两者都是 0~255 的整数。
    Si,j∈{0,…,255},Ki,jr∈{0,…,255}S_{i,j} \in \{0,\dots,255\}, \quad K^r_{i,j} \in \{0,\dots,255\}
  2. 逐位异或把它们写成 8 位二进制,每一位对照异或规则,得到新字节。
    Si,j′=Si,j⊕Ki,jrS'_{i,j} = S_{i,j} \oplus K^r_{i,j}
  3. 解密时再异或一次因为 $A \oplus A = 0$,所以 $(S \oplus K) \oplus K = S$。
    Si,j=Si,j′⊕Ki,jrS_{i,j} = S'_{i,j} \oplus K^r_{i,j}

7. 密钥扩展:一瓶底料兑出十种腌料

AES 的密钥扩展算法要从你手里那瓶种子密钥(比如 128 位 = 16 字节)出发,生成一轮接一轮不同的轮密钥。过程可以这样理解:种子密钥先被切成 4 个“字”(每个字 4 字节),然后像调配腌料一样不断往序列里添加新字。

每新增 4 个字(凑成下一轮 16 字节轮密钥)时,规则是:正常情况下,新的字等于它前面第 $N_k$ 个字的旧兄弟异或前一个字;但每组的第一个字,要先经过一个“调料加工”函数 $f$——先把前一个字循环左移一字节(RotWord),再逐字节查 S 盒(SubWord),最后异或上轮常数 Rcon。轮常数的存在是防止各组轮密钥出现对称性。

第 $r$ 轮的轮密钥就是第 $r$ 组 4 个字。由于每一轮的调料都不同,攻击者就算截获部分轮密钥,也无法推出种子密钥。

W[i]={W[i−Nk]⊕f(W[i−1]),i mod Nk=0W[i−Nk]⊕W[i−1],i mod Nk≠0W[i] = \begin{cases} W[i-N_k] \oplus f(W[i-1]), & i \bmod N_k = 0 \\ W[i-N_k] \oplus W[i-1], & i \bmod N_k \neq 0 \end{cases}
  1. 切字与补位密钥被切成 $N_k$ 个字 $W[0]\sim W[N_k-1]$,之后每个字由前面的字递推生成。
    种子密钥⇒W[0],W[1],…,W[Nk−1]\text{种子密钥} \Rightarrow W[0], W[1], \dots, W[N_k-1]
  2. 每组的第一个字做加工当 $i$ 是 $N_k$ 的倍数时,先对被旋转且被 S 盒替换的前一个字异或轮常数 Rcon,再与 $W[i-N_k]$ 异或。
    W[i]=W[i−Nk]⊕SubWord(RotWord(W[i−1]))⊕Rcon[i/Nk]W[i] = W[i-N_k] \oplus \mathrm{SubWord}(\mathrm{RotWord}(W[i-1])) \oplus \mathrm{Rcon}[i/N_k]
  3. 普通字直接异或其他位置的 $W[i]$ 就是前方隔 $N_k$ 的字与相邻前一字异或。
    W[i]=W[i−Nk]⊕W[i−1]W[i] = W[i-N_k] \oplus W[i-1]

8. 工作模式:一盒水果丁怎么分批榨

AES 一次只能处理 16 字节,那 1MB 的文件怎么办?答案是工作模式:定义如何把长消息切块,以及各块之间如何关联。三种最经典的模式如下。

ECB(电子密码本模式):每个 16 字节块独立用同一把密钥加密。像把水果丁按 16 颗一份,每份各自搅拌。缺点是:相同的明文块永远得到相同的密文块——如果加密一张企鹅图片,密文里还能看出企鹅轮廓,信息安全里著名的“ECB 企鹅漏洞”就是这个。

CBC(密码分组链接模式):每个明文块先与上一块的密文异或,再加密。像流水线上每一杯果汁都要掺入前一勺成品,因此相同明文块在不同位置会得到不同密文,安全得多,但也必须串行处理。

CTR(计数器模式):不直接加密明文,而是用计数器值(counter)作为输入,加密后得到一串伪随机密钥流,再与明文异或。这个模式可以并行计算,还能随机读取某一块密文而不影响其他块,因此广泛用于磁盘加密和无线网络。

实际工程中,CTR 模式还会搭配认证机制(如 GCM),防止攻击者篡改密文。选对工作模式,比选对算法本身更考验工程师的功力。

Ci=EK(Pi)C_i = E_K(P_i)
Ci=EK(Pi⊕Ci−1)C_i = E_K(P_i \oplus C_{i-1})
Ci=EK(ctri)⊕PiC_i = E_K(\mathrm{ctr}_i) \oplus P_i
  1. 生成密钥流块把计数器值 $\mathrm{ctr}_i$ 加密成伪随机块。
    Ki=EK(ctri)K_i = E_K(\mathrm{ctr}_i)
  2. 与明文异或密钥流块与第 $i$ 个明文块异或得到密文,解密时同样操作。
    Ci=Ki⊕PiC_i = K_i \oplus P_i

AI 应用场景

1. HTTPS 网页安全传输

阶段:数据加密与传输保护

解决的问题:传统 HTTP 是明文传输,抓包工具一抓就能看到你的账号密码。TLS 协议在握手阶段协商密钥后,用 AES-GCM(CTR 模式 + 认证)加密所有应用数据,既保证机密性又防止篡改。

具体案例:你在浏览器打开网上银行,地址栏亮起小锁。每次请求都在会话密钥下用 AES 加密;即便中间人截获了数据包,也只能看到密文果汁,还原不出任何字。

2. 全磁盘加密软件

阶段:静态数据加密

解决的问题:硬盘被盗或丢失后,直接拔出硬盘插到别的机器就能读取数据。BitLocker、LUKS 等工具使用 AES-XTS 模式(基于 CTR 演进),将每个扇区独立加密,支持随机读写且密文不可被拼接篡改。

具体案例:一台存有 10 万条用户数据的笔记本遗失,运维通过管理后台回收设备唤醒恢复密钥。数据在硬盘上始终以密文形式存在,没有密钥的拾到者拿到的是无法解读的密文。

3. 物联网传感器数据回传

阶段:端到端数据加密

解决的问题:智能电表、环境传感器每天回传海量小数据包,电池和 CPU 资源有限。AES-128 的硬件加速指令(AES-NI)在低功耗芯片上也能高效运行,配合 CCM/GCM 认证模式,防止攻击者伪造上报数据。

具体案例:农业物联网公司部署了 5000 个土壤传感器,每个节点每 15 分钟上报一次温湿度。数据采用 AES-128 加密后通过 LoRa 网络回传,平台侧解密入库,即使网关被入侵也无法伪造合法数据包。

Python 演示

python71 行
# AES 教学版: 演示四个轮操作与简化密钥扩展# 注意: 为便于阅读, 已简化 GF(2^8) 乘法与轮数, 正式加密请使用 PyCryptodome # 简化 S 盒: 非线性映射, 保证每个输入字节都有唯一输出SBOX = [(i * 7 + 1) % 256 for i in range(256)] def show(name, state):    print(name)    for row in state:        print(" ".join("%02x" % b for b in row))    print() def sub_bytes(state):    # 逐字节查 S 盒替换    return [[SBOX[state[r][c]] for c in range(4)] for r in range(4)] def shift_rows(state):    # 第 r 行循环左移 r 位    new = [row[:] for row in state]    for r in range(1, 4):        new[r] = new[r][r:] + new[r][:r]    return new def mix_columns(state):    # 简化列混合: 每个新字节混合本列相邻字节    new = [[0] * 4 for _ in range(4)]    for c in range(4):        a = state[0][c]; b = state[1][c]        d = state[2][c]; e = state[3][c]        new[0][c] = (a + b + e) % 256        new[1][c] = (a + b + d) % 256        new[2][c] = (a + d + e) % 256        new[3][c] = (b + d + e) % 256    return new def add_round_key(state, rk):    # 状态与轮密钥逐字节异或    return [[state[r][c] ^ rk[r][c] for c in range(4)] for r in range(4)] def key_expansion(key):    # 简化密钥扩展: 每轮轮密钥 = 种子密钥加轮号    rounds = []    for r in range(10):        rk = [[(key[r][c] + r * 17) % 256 for c in range(4)] for r in range(4)]        rounds.append(rk)    return rounds def encrypt_block(block, key_rounds):    state = [row[:] for row in block]    show("初态", state)    state = add_round_key(state, key_rounds[0])    show("AddRoundKey 前奏", state)    for r in range(1, 3):  # 演示两轮        state = sub_bytes(state)        show("SubBytes 第%d轮" % r, state)        state = shift_rows(state)        show("ShiftRows 第%d轮" % r, state)        state = mix_columns(state)        show("MixColumns 第%d轮" % r, state)        state = add_round_key(state, key_rounds[r])        show("AddRoundKey 第%d轮" % r, state)    return state if __name__ == "__main__":    block = [[0x00, 0x11, 0x22, 0x33],             [0x44, 0x55, 0x66, 0x77],             [0x88, 0x99, 0xaa, 0xbb],             [0xcc, 0xdd, 0xee, 0xff]]    keys = key_expansion(block)    print("=== AES 教学版演示 ===")    encrypt_block(block, keys)
目的:用不到 80 行实现 AES 四个核心轮操作的简化版,直观打印每个工序对 4×4 状态矩阵的影响,帮助初学者建立“轮函数”的直觉。
  1. SBOX = [(i * 7 + 1) % 256 for i in range(256)]生成一个简单的非线性 S 盒,保证字节替换不可被线性方程描述。
  2. new[r] = new[r][r:] + new[r][:r]实现 ShiftRows 的行循环左移,$r$ 等于行号。
  3. (a + b + e) % 256简化版列混淆,让一列中相邻字节互相“串味”,演示扩散效果。
  4. state[r][c] ^ rk[r][c]逐字节异或,正是 AddRoundKey 的核心运算。
  5. (key[r][c] + r * 17) % 256简化密钥扩展,用轮号扰动种子密钥,生成每轮不同的轮密钥。
  6. state = add_round_key(state, key_rounds[0])主流程先做一次“前奏加料”,然后进入多轮循环。
  7. if __name__ == "__main__":可执行入口,直接运行会看到每一道工序后的矩阵变化。

常见误区

误区我以为 AES 和 RC4 一样,是逐字节加密的流密码,所以用起来很灵活,不需要管数据长度。

正解AES 是分组密码,一次固定处理 16 字节。它本身只能加密一个块,长数据必须借助工作模式(CBC、CTR 等)才能变成流式的加密流程。把 AES 当流密码用,会导致块边界处理错误,出现数据错位。

为何常见:因为实际使用时,CTR 模式看起来像在“流式”加密,容易让人误解 AES 本质是流密码。

误区AES 都这么安全了,ECB 模式把每块独立加密,抗暴力破解,怎么会不安全?

正解AES 的安全针对“给定密文反推明文”。ECB 的致命伤是相同明文块永远生成相同密文块,攻击者可以通过比较密文块发现明文重复规律。经典例子是用 AES-ECB 加密一张企鹅图片,密文仍能看出企鹅轮廓。CBC 通过引入前一块密文和 IV 打破这种规律。

为何常见:初学者只关注算法本身强度,忽略了工作模式定义的“块与块之间关系”对整体安全的决定性影响。

误区既然 128 位 AES 有 10 轮,256 位有 14 轮,那 256 位一定比 128 位安全 2 倍,所有系统都应该上 256 位。

正解128 位密钥有 $2^{128}$ 种可能,现有算力暴力穷举完全不现实。若采用 256 位,安全性提升主要集中在抵抗未来量子计算机的 Grover 算法(可将暴力搜索降至 $2^{128}$)。对大多数业务,128 位已经足够;真正的风险往往来自密钥管理不当(硬编码、弱密码),而不是密钥长度不够。

为何常见:“越长越好”符合直觉,容易让人忽略密码系统中攻击面最弱的一环往往在流程和管理。

误区S 盒就是 256 个随机数字组成的查找表,像彩票号码一样没有规律,用来把输入打乱。

正解AES 的 S 盒有严格数学构造:先对字节在 $GF(2^8)$ 中求乘法逆元,再做一次仿射变换。这套设计可以抵抗代数攻击(如插值攻击),也让 S 盒具备良好的非线性度和差分均匀性。随机表反而可能出现弱密钥或数学漏洞。

为何常见:从使用视角看,S 盒只是在查表,但设计视角下它是 AES 抗密码分析的数学根基。

误区AES 这么厉害,一定是把算法代码藏起来,黑客不知道原理就没法破解。

正解密码学界遵循 Kerckhoffs 原则:算法公开,唯有密钥保密。AES 的算法细节、S 盒、矩阵常量全部公开,经过全球二十年检验仍安全。如果靠隐藏算法来保安全,一旦算法泄露就全盘崩溃,且无法公开评估安全性。

为何常见:普通人习惯把安全寄托在“别人不知道”上,而成熟的安全体系把安全寄托在“即使知道一切也解不开”上。

面试题

Q1. AES 加密一个数据块的大小是多少位?

单选题 · easy

  • A.64 位
  • B.128 位← 正确答案
  • C.256 位
  • D.512 位

答案:B。AES 是分组密码,固定处理 128 位(16 字节)明文块,无论密钥是 128/192/256 位。64 位是 DES 的分组大小,256 位是 AES 的一种密钥长度而非分组长度。

Q2. AES-128 的加密轮数是多少?

单选题 · mid

  • A.8 轮
  • B.10 轮← 正确答案
  • C.12 轮
  • D.14 轮

答案:B。AES 轮数由公式 $N_r = 6 + \max(N_k, N_b)$ 决定,128 位密钥对应 $N_k=4$,所以 $N_r=10$。192 位对应 12 轮,256 位对应 14 轮。

Q3. SubBytes 步骤中 S 盒的作用是什么?

单选题 · mid

  • A.把字节循环左移
  • B.把字节按非线性映射替换← 正确答案
  • C.把字节与轮密钥异或
  • D.把一列字节混合

答案:B。S 盒是一个 256 格查表,把每个输入字节非线性替换成另一个字节,是整个 AES 中提供非线性的关键步骤,用于抵抗线性攻击和代数攻击。行移位、列混淆、轮密钥加分别由其他步骤完成。

Q4. ShiftRows 中第 2 行(r=1)循环左移几位?

单选题 · easy

  • A.0 位
  • B.1 位← 正确答案
  • C.2 位
  • D.3 位

答案:B。ShiftRows 规则是第 $r$ 行循环左移 $r$ 位。第 0 行不动,第 1 行左移 1 位,第 2 行左移 2 位,第 3 行左移 3 位。

Q5. MixColumns 在 AES 中主要提供什么安全特性?

单选题 · mid

  • A.置换
  • B.非线性
  • C.扩散← 正确答案
  • D.认证

答案:C。MixColumns 把每列的 4 个字节与固定矩阵相乘,使一个字节的变化扩散到整列,产生雪崩效应,属于扩散(diffusion)。非线性主要由 SubBytes 提供,置换由 ShiftRows 提供,认证需要额外认证模式。

Q6. AES 密钥扩展中,处理每组第一个字时依次执行哪三个操作?

单选题 · hard

  • A.SubWord、RotWord、加 Rcon
  • B.RotWord、SubWord、异或 Rcon← 正确答案
  • C.RotWord、加 Rcon、SubWord
  • D.异或 Rcon、RotWord、SubWord

答案:B。当索引 $i$ 是 $N_k$ 的倍数时,先对前一个字做循环左移(RotWord),再逐字节查 S 盒(SubWord),最后与轮常数 Rcon 异或。顺序不能颠倒,这是 AES 标准定义的。

Q7. ECB 模式最主要的弱点是?

单选题 · mid

  • A.加密速度太慢
  • B.相同明文块产生相同密文块← 正确答案
  • C.IV 需要保密
  • D.不支持并行运算

答案:B。ECB 将每个明文块独立加密,相同明文块总是得到相同密文块,密文会泄露明文模式(如企鹅图片轮廓)。CBC 通过 IV 和前一块密文解决该问题;ECB 支持并行。

Q8. 关于 CBC 模式的初始化向量 IV,下列说法正确的有?

多选题 · mid

  • A.IV 可以重复使用
  • B.IV 不需要保密,但必须随机或不可预测← 正确答案
  • C.IV 需要和密钥一样严格保密
  • D.IV 相同且首块相同时,CBC 的首个密文块也相同← 正确答案

答案:BD。CBC 中 IV 通常公开传输,但必须随机且不重复使用;若 IV 可预测,攻击者可发起选择明文攻击。IV 重复会使相同明文的第一个块产生相同密文,因此“能重复”是错的;IV 无需保密,所以“严格保密”也不对。

Q9. AES 支持哪些合法密钥长度?

多选题 · hard

  • A.64 位
  • B.128 位← 正确答案
  • C.192 位← 正确答案
  • D.256 位← 正确答案

答案:BCD。AES 标准规定的三种密钥长度是 128、192、256 位,分别对应 10、12、14 轮。64 位是 DES 的密钥长度,512 位不是 AES 的合法规格。

Q10. 关于 CTR 计数器模式,下列说法正确的有?

多选题 · hard

  • A.支持密文随机访问← 正确答案
  • B.加密过程可以并行计算← 正确答案
  • C.计数器值可以随意重复
  • D.本身提供完整性认证

答案:AB。CTR 的每个数据块通过加密计数器值生成密钥流并异或得到密文,块之间无依赖,因此可并行且可随机访问。计数器重复会破坏安全性,不能随意重复;CTR 本身不提供认证,需要配合 GCM 等认证机制防篡改。