文章

AES算法简介

AES算法简介

目录

  1. AES算法描述
  2. 数学基础
  3. 设计思想
  4. 基本变换
  5. 密钥扩展
  6. 加密过程
  7. 解密过程
  8. 常见攻击手段

一、AES算法概述

1.发展背景

1997年4月15日,美国ANSI发起征集AES (Advanced Encryption Standard) 的活动,并为此成立了AES工作小组。此次活动的目的是确定一个非保密的、可以公开技术细节的、全球免费使用的分组密码算法,以作为新的数据加密标准。

对AES的基本要求是:比三重DES快,至少与三重DES一样安全,数据分组长度128bit,密钥长度为128/192/256bit,可应用于公共领域并免费提供,应至少在30年内是安全的。

2000年10月,Rijndael算法凭借其安全性、高效率、可实现和使用灵活等优点成为美国新的高级加密标准(AES)

Rijndael算法的原型是Square算法,它的设计策略是宽轨迹策略。优点是能很好地评估算法抵抗差分和线性密码攻击的能力。

2.整体认识

AES算法选定的Rijndael算法中,分组长度固定为 128bit(16byte)。而AES-128、AES-192、AES-256 中的数字表示的是密钥长度,不是分组长度。

算法密钥长度 Nk(32-bit 字)轮数 Nr分组长度
AES-128410128 bit
AES-192612128 bit
AES-256814128 bit

AES的基本运算单位是字节(Byte),加密和解密过程都是在一个4X4的字节矩阵上运作,这个矩阵又称为 “体(state)” 或者 “状态” 。字节矩阵初始值是一个明文块。

AES 是一个 “代换-置换网络”(Substitution-Permutation Network,SPN)。加密过程执行多轮以下操作:

  1. 字节代替
  2. 行移位
  3. 列混合
  4. 轮密钥加

最后一个加密循环中省略列混合步骤。

解密过程除了轮密钥加外,其它都是加密过程的逆运算:

  1. 逆行移位
  2. 逆字节代替
  3. 轮密钥加
  4. 逆列混合

可以看到解密和加密的运算过程不是完全颠倒。

二、数学基础

1.$Byte$ 的多项式表示

AES算法将 $b_{7}b_{6}b_{5}b_{4}b_{3}b_{2}b_{1}b_{0}$ 构成的字节 b 看成系数属于 GF(2)、次数小于 8 的多项式: \(b_7x^7+b_6x^6+\cdots+b_1x+b_0\)

例如:

1
0x57 = 01010111₂

所以: \(\texttt{0x57}=x^6+x^4+x^2+x+1\)

每个 bit 就是相应次数项的系数。

这样一来,两个字节相加就是多项式系数异或:

1
2
3
0x57 + 0x83
= 0x57 XOR 0x83
= 0xd4

2.有限域 $GF(2^8)$

AES定义的字节域为:

\[GF(2^8)=GF(2)[x]/(m(x))\]

其中 $m(x)=x^8+x^4+x^3+x+1$ ,二进制表示为

1
1 0001 1011₂ = 0x11b

可见有限域$GF(2^8)$上的乘法,就是两个多项式正常相乘,系数模2,最后模多项式 $m(x)$

因为 $m(x)$ 不可约,所以所有非零元素都存在乘法逆元。

易知以上乘法的单位元为0x01 ,可通过扩展欧几里得算法求得乘法逆元:

\[a(x)a^{-1}(x)+m(x)c(x)=1\]

xtime

在有限域 $GF(2^8)$上还定义了一个运算,称为x乘法,其定义为: \(x\cdot b(x)=b_{7}x^8+b_{6}x^7+b_{5}x^6+b_{4}x^5+b_{3}x^4+b_{2}x^3+b_{1}x^2+b_{0}x \ \ mod \ \ m(x)\) 简化流程如下:

  1. 如果$b_{7}=0$ ,直接在字节内左移一位(最后一位补0)
  2. 如果$b_{7}=1$ ,还要再与0x1b 异或

这里使用 0x1b 而不是 0x11b,是因为左移产生的 $x^8$ 项已经被消去,只需异或模多项式的低 8 bit。

x的幂乘运算可以重复应用xtime来实现(快速幂)

例如,计算 $57\cdot 13$ : \(\begin{align} &57\cdot02=xtime(57)=AE \\ &57\cdot04=xtime(AE)=47 \\ &57\cdot08=xtime(47)=8E \\ &57\cdot10=xtime(8E)=07 \\ &57\cdot13=57\cdot(01\oplus 02\oplus 10) \\ &=57\oplus AE\oplus 07=FE \end{align}\)

3.系数在 $GF(2^8)$ 上的多项式

4个字节的向量可以表示为系数在$GF(2^8)$ 上的次数小于4的多项式。

加法

多项式的加法就是对应系数相加。换句话说就是4字节的逐比特异或、

乘法

取模 $M(x)=x^4+1$ ,这样使得次数小于4的多项式的乘积次数仍然小于4。

设 $a(x)=a_{3}x^3+a_{2}x^2+a_{1}x+a_{0}$,$b(x)=b_{3}x^3+b_{2}x^2+b_{1}x+b_{0}$,则:

\[c(x)=a(x)\otimes b(x)=c_{3}x^3+c_{2}x^2+c_{1}x+c_{0}\]

由于 $x^j \ \ mod(x^4+1)=\ \ x^{j \ \ mod \ \ 4}$ ,所以:

\[\begin{pmatrix} c_{0} \\ c_{1} \\ c_{2} \\ c_{3} \\ \end{pmatrix}= \begin{pmatrix} a_{0} & a_{3} & a_{2} & a_{1} \\ a_{1} & a_{0} & a_{3} & a_{2} \\ a_{2} & a_{1} & a_{0} & a_{3} \\ a_{3} & a_{2} & a_{1} & a_{0} \\ \end{pmatrix} \begin{pmatrix} b_{0} \\ b_{1} \\ b_{2} \\ b_{3} \\ \end{pmatrix}\]

显然只要矩阵

\[\begin{pmatrix} a_{0} & a_{3} & a_{2} & a_{1} \\ a_{1} & a_{0} & a_{3} & a_{2} \\ a_{2} & a_{1} & a_{0} & a_{3} \\ a_{3} & a_{2} & a_{1} & a_{0} \\ \end{pmatrix}\]

可逆,多项式$a(x)=a_{3}x^3+a_{2}x^2+a_{1}x+a_{0}$ 就是模 $x^4+1$ 可逆的。

容易发现,x模乘多项式相当于字节循环移位。

三、设计思想

AES 的设计思想可以概括为:

用少量结构简单、可逆且高效的基本变换,通过多轮“非线性混淆 + 线性扩散 + 密钥注入”,让明文、密钥和密文之间形成复杂关系。

AES的设计力求满足以下3条标准:

  1. 抵抗所有已知攻击
  2. 在多个平台上速度快,编码紧凑
  3. 设计简单

宽轨迹策略

AES 设计中非常重要的思想是 Wide Trail Strategy(宽轨迹策略)。

它的核心是:

  • S-box 提供局部非线性;
  • ShiftRows 把字节跨列移动;
  • MixColumns 让一列中的字节互相影响;
  • 多轮组合后,差分路径或线性路径必须经过大量活跃 S-box。

“活跃 S-box” 指输入和输出之间存在非零差分或非平凡线性关系的 S-box。

攻击者想利用差分或线性关系,就必须同时处理很多 S-box,而每个 S-box 的最大差分概率、最大线性偏差都受到限制。因此整体攻击复杂度会快速上升。

非线性层

AES采用精妙数学设计的S盒:求逆元+仿射变换。这让它的安全性被很好的确定,比如差分均匀性、非线性度等。它有如下优点:

  • 非线性度高;
  • 差分均匀性好;
  • 不容易被线性密码分析和差分密码分析利用;
  • 没有明显的固定点和简单对称结构;
  • 映射是双射,保证可逆。

线性层

ShiftRows 和 MixColumns操作都属于线性层,但它们的分工不同

ShiftRows负责重新排列位置,它不改变字节值,只改变字节所在的列。

MixColumns负责在每列内做有限域矩阵乘法,它会把一个字节的影响扩散到同一列的多个字节。

如果只有 MixColumns 而没有 ShiftRows,每一列之间联系不足;如果只有 ShiftRows 而没有 MixColumns,只是位置重排,无法充分混合字节值。两者配合才能快速形成全局扩散。

密钥扩展的设计思想

AES 不在每轮重复使用原始密钥,而是生成不同的轮密钥。

密钥扩展同时使用:

  • RotWord:改变字节位置;
  • SubWord:引入 S-box 非线性;
  • Rcon:破坏轮之间的对称性;
  • 异或递推:高效地产生新字。

设计目标是避免:

  • 轮密钥之间过于相似;
  • 某些密钥字节不影响后续轮;
  • 出现明显的重复周期;
  • 相关密钥攻击过于容易。

密钥扩展的目的是原始密钥的每个 bit 尽快影响所有轮密钥。

四、基本变换

AES算法中,加密和解密操作都是在一个4X4的字节矩阵上运作,这个矩阵称为状态(State)。状态用以字节为基本构成元素的矩阵阵列来表示,该阵列每列4byte数据,即32bit,因而明文列数为分组长度除以32,通常记为$N_{b}$。 \(N_{b}=\frac{分组长度(bit)}{32}\) 一般的,Rijndael算法列数$N_{b}$ 可以取的值为4、6、8,对应的明文分组长度为128、192、256bit。而AES算法的分组长度固定为128bit,因此AES明文列数等于固定值$N_{b}=4$。

BQACAgUAAyEGAASHRsPbAAEZjF1qhywTFFf0te7m7cUEwt7GaO8oVAACwy8AAlXsOVR7mEvZ-v6skD0E.png

初始明文矩阵、种子密钥和轮数

AES算法中初始状态矩阵由1组长度为 128bit 明文分组构成,以字节为单位,则总共有16byte,记为$B_{0},B_{1},B_{2},\dots,B_{14},B_{15}$。加密结束时,输出密文128bit也是以列方法按相同的顺序提取。

BQACAgUAAyEGAASHRsPbAAEZjGJqhyxAyWo10niVCIcVcRN7mPbc2wACyC8AAlXsOVTwzgclKKhwYD0E.png

种子密钥类似地用一个以字节为元素的矩阵阵列表示,该阵列有4行,列数记为 $N_{k}$ \(N_{k}=\frac{密钥长度(bit)}{32}\) AES算法的密钥长度的列数为128bit、192bit、256 bit三种,因此不同密钥长度 $N_{k}$可以取的值分别为4、6、8。

BQACAgUAAyEGAASHRsPbAAEZjGNqhyxDJ-Yo4ijZwwl32XfkfVPzGwACyS8AAlXsOVRZ3290Ur13jD0E.png

迭代的轮数记为$N_{r}$ ,$N_{r}$ 与$N_{b}$ 和$N_{k}$ 有关,下表给出了其关系:

| $N_{r}$ | $N_{b}=4$ | $N_{b}=6$ | $N_{b}=8$ | | ——— | ——— | ——— | ——— | | $N_{k}=4$ | 10 | 12 | 14 | | $N_{k}=6$ | 12 | 12 | 14 | | $N_{k}=8$ | 14 | 14 | 14 | 从表中可以看出,AES的迭代轮数为10、12或14

Rijndael的轮函数由4个不同的计算部件组成,分别是字节代换(ByteSub),行移位(ShiftRow),列混合(MixColumn)和密钥加(AddRoundKey)

字节代换(ByteSub)

字节代换是非线性变换。代换表,也就是S盒,有两个设计原则:

  1. S盒是可逆的
  2. 不能存在这种情况:第 i 行第 j 列位置上的值为 ij

S盒由以下两个变换合成得到:

  1. 在有限域 $GF(2^8)$ 上求字节的乘法逆元,00的逆就是自身
  2. 对字节的逆元做如下的可逆变换:
\[\begin{pmatrix} y_{0} \\ y_{1} \\ y_{2} \\ y_{3} \\ y_{4} \\ y_{5} \\ y_{6} \\ y_{7} \end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\ 1 & 1 & 0 & 0 & 0 & 1 & 1 & 1 \\ 1 & 1 & 1 & 0 & 0 & 0 & 1 & 1 \\ 1 & 1 & 1 & 1 & 0 & 0 & 0 & 1 \\ 1 & 1 & 1 & 1 & 1 & 0 & 0 & 0 \\ 0 & 1 & 1 & 1 & 1 & 1 & 0 & 0 \\ 0 & 0 & 1 & 1 & 1 & 1 & 1 & 0 \\ 0 & 0 & 0 & 1 & 1 & 1 & 1 & 1 \\ \end{pmatrix} \begin{pmatrix} x_{0} \\ x_{1} \\ x_{2} \\ x_{3} \\ x_{4} \\ x_{5} \\ x_{6} \\ x_{7} \end{pmatrix} + \begin{pmatrix} 1 \\ 1 \\ 0 \\ 0 \\ 0 \\ 1 \\ 1 \\ 0 \end{pmatrix}\]

S盒变换也可以通过查 16X16 的表来进行,映射原则:输入字节的前4bit指定S 盒的行值,后4bit指定S盒的列值,行和列所确定S盒位置的元素作为输出。

BQACAgUAAyEGAASHRsPbAAEZjI5qhzH4KMhWfK4BWkQwz9APV2AhgwAC-S8AAlXsOVTWGMq-fri9zz0E.png

ByteSub的逆变换可通过以下两步实现:首先进行仿射变换的逆变换,再求在$GF(2^8)$ 上的逆元

行移位(ShiftRow)

在AES算法中,行移位作用于S盒的输出。其中,状态矩阵的4个行循环以字节为基本单位进行左移。

第一行循环左移0字节,第二行循环左移1字节,第三行循环左移2字节,第四行循环左移3字节。这可以使列得到完全的重排。

BQACAgUAAyEGAASHRsPbAAEZnNdqiHrC3rokGqj-_diAKWEbAaBYawACmS8AAgK8QFTzH9_GBTehxj0E.png

列混合(MixColumn)

列混合(MixColumn)操作是将状态矩阵的每一列视为 $GF(2^8)$ 上的多项式,再分别与多项式 $a(x)$ 进行模 $x^4+1$ 的乘法。其中 $a(x)$ 可逆: \(a(x)=03x^3+01x^2+01x+02\) 列混合操作可用以下的公式表示: \(c(x)=a(x)\otimes b(x)=a(x) \times b(x) \ \ mod (x^4+1)\) 也可以用矩阵式表示:

\[\begin{pmatrix} c_{0} \\ c_{1} \\ c_{2} \\ c_{3} \\ \end{pmatrix} = \begin{pmatrix} 02 & 03 & 01 & 01 \\ 01 & 02 & 03 & 01 \\ 01 & 01 & 02 & 03 \\ 03 & 01 & 01 & 02 \\ \end{pmatrix} \begin{pmatrix} b_{0} \\ b_{1} \\ b_{2} \\ b_{3} \\ \end{pmatrix}\]

轮密钥加(AddRoundKey)

最后一项基本操作是轮密钥加,是将列混合的输出状态矩阵与子密钥状态进行异或运算(子密钥是从初始密钥派生而来的)。子密钥状态矩阵长度等于明文状态矩阵长度。

BQACAgUAAyEGAASHRsPbAAEZnQRqiICibgOrzv8CDJ3Y5sUN8K3-6AAC2S8AAgK8QFSAZ91IxoHzzD0E.png

五、密钥扩展

密钥扩展是从种子密钥获得轮密钥的过程,有以下基本原则:

  1. 轮密钥比特数=分组长度 $\times$ (轮数 $+1$ )
  2. 种子密钥被扩展成扩展密钥
  3. 轮密钥从扩展密钥中取,每轮取 $N_{b}$ 个字(32bit)

符号说明

$W[\ \ ]$ : 扩展密钥是以字(32bit)为元素的一维数组,表示为 $W[ \ \ N_{b}\cdot (N_{r}+1)\ \ ]$ ,其中,前 $N_{k}$ 个字取为种子密钥。

$key[\ \ ]$ : $key[\ \ 4\cdot N_{k}\ \ ]$ 为种子密钥,看作以字节为元素的一维数组

$SubByte$ : 字节代换

$RotByte$ : 以字节为单位的循环左移位,输入输出都是字

$Rcon[i]$ : 轮常数,为一个字。定义为: \(Rcon[i]=(RC[i],00,00,00)\) 其中, $RC[i]$ 是 $GF(2^8)$ 中值为 $x^{i-1}$ 的元素,即有限域 $GF(2^8)$ 上的x乘

根据RC计算方法,前10轮$RC[i]$ 的值如下表所示:

i12345678910
$RC[i]$01020408102040801b36

算法伪代码

$N_{k}\leq6$

1
2
3
4
5
6
7
8
9
10
11
12
KeyExpansion(byte key[4*N_k],W[N_b*(N_r+1)]){
    int i;
    for(i=0;i<N_k;i++){
        W[i]=(key[4*i],key[4*i+1],key[4*i+2],key[4*i+3]);
    }
    for(i=N_k;i<N_b*(N_r+1);i++){
        temp=W[i-1];
        if(i%N_k==0)
            temp=SubByte(RotByte(temp))^Rcon[i/N_k];
        W[i]=W[i-N_k]^temp;
    }
}

可以看出,扩展密钥的前 $N_{k}$ 个字即为种子密钥,之后的每个字 $W[i]$ 等于前一个字$W[i-1]$ 与 前$N_{k}$ 个位置的字 $W[i-N_{k}]$ 的异或;不过当 $N_{k} \mid i$ 时,需要先将前一个字$W[i-1]$ 作如下处理:

1字节的循环左移位RotByte->用S盒进行变换SubByte->与轮常数$Rcon[i/N_{k}]$ 进行异或

下图展示了 AES-128 的密钥扩展过程

BQACAgUAAyEGAASHRsPbAAEZoPpqiTGpvW4IWnGWaFSkAuxRkbUwUQACXiQAAgK8SFTHVeGxRVSb9D0E.png

$N_{k}>6$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
KeyExpansion(byte key[4*N_k],W[N_b*(N_r+1)]){
    int i;
    for(i=0;i<N_k;i++){
        W[i]=(key[4*i],key[4*i+1],key[4*i+2],key[4*i+3]);
    }
    for(i=N_k;i<N_b*(N_r+1);i++){
        temp=W[i-1];
        if(i%N_k==0)
            temp=SubByte(RotByte(temp))^Rcon[i/N_k];
        else if(i%N_k==4)
            temp=SubByte(temp);
        W[i]=W[i-N_k]^temp;
    }
}

$N_{k}>6$ 与$N_{k}\leq6$ 的密钥扩展算法的区别在于,除了$N_{k} \mid i$ 要进行特殊处理,在 $i\ \ mod \ \ N_{k }=4$ 时,也要对前一个字$W[i-1]$ 经过SubByte变换

轮密钥选取

轮密钥 i 由扩展密钥 $W[N_{b}\cdot i]$ 到 $W[N_{b}\cdot (i+1)-1$ 给出:

BQACAgUAAyEGAASHRsPbAAEZpCpqiWHvtEQl3MgcdtzTHKti3bBUHwACoigAAgK8SFTHH38B3EZMuT0E.png

六、加密过程

AES-128 使用 16 byte 明文块和 16 byte 密钥,共 10 轮:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
输入明文
        │
        ▼
AddRoundKey            
        │
        ▼
┌──────────────────┐
│ SubBytes         │
│ ShiftRows        │  第 1~9 轮
│ MixColumns       │
│ AddRoundKey      │
└──────────────────┘ 
        │
        ▼
SubBytes
ShiftRows              第 10 轮:没有列混合
AddRoundKey
        │
        ▼
输出密文

可写成伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
state = plaintext
KeyExpansion(key,ExpandedKey)
state = AddRoundKey(state, ExpandedKey)
int i;
for(i=1;i<N_r;i++):
    state = SubBytes(state)
    state = ShiftRows(state)
    state = MixColumns(state)
    state = AddRoundKey(state, ExpandedKey+N_b*i)

state = SubBytes(state)
state = ShiftRows(state)
state = AddRoundKey(state, ExpandedKey+N_b*N_r)

七、解密过程

BQACAgUAAyEGAASHRsPbAAEZp7JqiaHRl3Maq0P-2aJNymnctWyhCAACKyMAAkreSVTyEilfc4FSXD0E.png

AES密码算法采用的是S-P网络结构,加密过程与解密过程不同,解密过程是加密过程的逆过程。

AES解密过程中,轮密钥的次序与加密过程正好相反,解密过程输入密文,先做一次轮密钥加,然后进行r轮变换。前 r-1轮中,每轮基本操作为逆行移位、逆字节代替、轮密钥加和逆列混合,而最后一轮操作为逆行移位、逆字节代替和轮密钥加(没有逆列混合)。

逆字节代替(InvSubBytes)

逆S盒:

BQACAgUAAyEGAASHRsPbAAEZp7lqiaQEnPT5-a-DIyP1WaNWvMkkiQACOiMAAkreSVSa-XY9eCDF9j0E.png

S盒对应的运算:

1.逆仿射变换:

\[\begin{pmatrix} b_0 \\ b_1 \\ b_2 \\ b_3 \\ b_4 \\ b_5 \\ b_6 \\ b_7 \end{pmatrix} = \begin{pmatrix} 0&0&1&0&0&1&0&1\\ 1&0&0&1&0&0&1&0\\ 0&1&0&0&1&0&0&1\\ 1&0&1&0&0&1&0&0\\ 0&1&0&1&0&0&1&0\\ 0&0&1&0&1&0&0&1\\ 1&0&0&1&0&1&0&0\\ 0&1&0&0&1&0&1&0 \end{pmatrix} \cdot \begin{pmatrix} b'_0 \\ b'_1 \\ b'_2 \\ b'_3 \\ b'_4 \\ b'_5 \\ b'_6 \\ b'_7 \end{pmatrix} + \begin{pmatrix} 1 \\ 0 \\ 1 \\ 0 \\ 0 \\ 0 \\ 0 \\ 0 \end{pmatrix}\]

2.在$GF(2^8)$ 上求逆元

逆行移位

与行移位相反,逆行移位循环右移。

若AES算法中 $N_{b}$ 为4,即第1行循环右移0字节,第2行循环右移1字节,第3行循环右移2字节,第4行循环右移3字节。

逆列混合

逆列混合操作与列混合操作一样,只是选择相乘的固定多项式不同,逆列混合与固定多项式 $d(x)=0B x^3+0Dx^2+09x+0E$ 相乘,然后模 $x^4+1$ 。同理可以用矩阵乘法表示:

\[\begin{pmatrix} b_0 \\ b_1 \\ b_2 \\ b_3 \end{pmatrix} = \begin{pmatrix} \mathrm{0E} & \mathrm{0B} & \mathrm{0D} & \mathrm{09}\\ \mathrm{09} & \mathrm{0E} & \mathrm{0B} & \mathrm{0D}\\ \mathrm{0D} & \mathrm{09} & \mathrm{0E} & \mathrm{0B}\\ \mathrm{0B} & \mathrm{0D} & \mathrm{09} & \mathrm{0E} \end{pmatrix} \cdot \begin{pmatrix} c_0 \\ c_1 \\ c_2 \\ c_3 \end{pmatrix}\]

八、常见攻击手段

AES 只负责构造一个安全的分组密码,不负责解决所有密码学问题。它本身不负责:

  • 密钥交换;
  • 用户身份认证;
  • 密码存储;
  • 防止重放;
  • 处理任意长度消息;
  • 提供完整性认证;
  • 解决密钥生命周期管理。

CTF 中的 AES 题目通常不是要求你破解 AES 算法本身,而是考察上述这些是否正确实现。

完整、正确实现的 AES-128/192/256 一般不会被直接暴力破解

1.Square Attack

积分攻击通过构造 256 个特殊明文,让 AES 内部的某些字节在多轮传播后满足 XOR 平衡条件,再通过猜测最后一轮密钥并逆向验证,筛选出正确密钥。它利用的是 AES 结构的可预测整体性质,主要针对减少轮数或错误实现,而不是直接击破标准 AES。

(挖个坑,找时间深入学一下这个攻击0ctf 2016 - people square)

2. ECB分组模式

ECB 没有随机化,也没有块之间的关联,因此会泄露明文结构。

典型特征

  • 加密接口固定使用同一把密钥;
  • 输入可以由选手控制;
  • 密文长度按 16 byte 分块;
  • 相同明文块产生相同密文块。

3.CBC模式相关攻击

  • 字节反转攻击
  • Padding Oracle
  • IV 使用错误

详细参考分组模式的常见攻击方法。

4.Nonce 重用攻击

CTR 模式把 AES 作为密钥流生成器: \(C_i=P_i\oplus KS_i\) 其中: \(KS_i=AES_K(nonce\parallel counter_i)\) 如果同一密钥下重复使用 nonce 和计数器,两个消息会使用相同密钥流: \(C_1=P_1\oplus KS\) \(C_2=P_2\oplus KS\) 异或后: \(C_1\oplus C_2=P_1\oplus P_2\) 密钥流被抵消。

5.弱密钥派生

很多题目表面上使用 AES,真正的弱点却是使用弱密钥:

  • 密码是短字符串;
  • 密钥来自用户名、时间戳、生日等可猜信息;
  • 使用 MD5/SHA-1 一次哈希代替密码派生函数;
  • salt 固定或没有 salt;
  • hex 字符串和原始 byte 混淆;
  • 不同用户或不同文件共用相同密钥。

6.把 AES 错当作哈希

CTF 中可能看到错误设计:

1
hash(message) = AES_K(message) 的最后一块

这类设计可能导致:

  • 可构造碰撞;
  • 长度扩展问题;
  • 块重排攻击;
  • 截断或拼接攻击;
  • 认证范围不完整。
本文由作者按照 CC BY 4.0 进行授权