一、定义
分组加密又称块加密Block Cipher,就是把大段的plaintext,分块加密传输。而One-key Block Cipher通常是以发送方和接收方共享一个Key作为加解密密钥。数学定义如下:
One-key Block Cipher 是一个五元组 ( M , C , K , E k , D k ) (\mathcal{M,C,K},E_k,D_k) (M,C,K,Ek,Dk), 其中
- M \mathcal{M} M是原文文本空间, C \mathcal{C} C是加密文本空间, K \mathcal{K} K是键值空间
- 所有键值 k ∈ K k\in\mathcal{K} k∈K都能作为加解密密钥
- E k E_k Ek和 D k D_k Dk是以密钥为 k k k的加解密函数。满足对任意 m ∈ M m\in\mathcal{M} m∈M,有 D k ( E k ( m ) ) = m D_k(E_k(m))=m Dk(Ek(m))=m
- 加密文本可以表示为 c = E k ( m ) c=E_k(m) c=Ek(m), c ∈ C c\in\mathcal{C} c∈C, E k E_k Ek 通常会对 m m m 进行分块加密
- 解密文本可以表示为 m = D k ( c ) m=D_k(c) m=Dk(c), D k D_k Dk 通常对 c c c 进行分块解密。
二、攻击
- Ciphertext-only 攻击:攻击人通过监听获取加密文本 c c c 的情况下,推断出加密函数 D k D_k Dk ,或键值 k k k或者原文文本 m m m
- Known-plaintext 攻击:攻击人通过获取到的加密文本-原文文本对 ( c , m ) (c,m) (c,m) 推断出加密函数 D k D_k Dk 或者键值 k k k
三、加解密函数的设计
3.1 失败的加解密函数
- Permutation,即通过字母映射表将原文的字母一一变换为新的文本。缺点:可以通过字母频率推断映射。
- one-time pad,每次通信都使用不同的密钥,使用一次之后当即销毁密钥本身。这种加解密被密码学之父香农证明是不可破解的,但是开销太高,不实际。
3.2 数学概念补充
3.2.1 阿贝尔群
介绍线性与非线性函数之前,首先介绍一下阿贝尔群,一个阿贝尔群 A A A对某个运算符 ⊕ \oplus ⊕满足
- 对该运算封闭,对任意 x ∈ A , y ∈ A x\in A, y\in A x∈A,y∈A有 x ⊕ y ∈ A x\oplus y\in A x⊕y∈A
- 运算交换律,对任意 x ∈ A , y ∈ A x\in A, y\in A x∈A,y∈A有 x ⊕ y = y ⊕ x x\oplus y=y \oplus x x⊕y=y⊕x
- 运算结合律,对任意 x ∈ A , y ∈ A , z ∈ A x\in A, y\in A, z\in A x∈A,y∈A,z∈A有 ( x ⊕ y ) ⊕ z = x ⊕ ( y ⊕ z ) (x\oplus y)\oplus z=x \oplus (y\oplus z) (x⊕y)⊕z=x⊕(y⊕z)
- 存在幺元 o ∈ A o\in A o∈A,使得对任意 x ∈ A x\in A x∈A 有 x ⊕ o = x x\oplus o =x x⊕o=x
- 存在逆元,对任意 x ∈ A x\in A x∈A都有其对应的的逆元 i ∈ A i\in A i∈A 使得 x ⊕ i = 0 x\oplus i = 0 x⊕i=0
3.2.2 线性变换与仿射变换
- 线性变换:从一个阿贝尔群 ( A , + ) (A,+) (A,+) 到另外一个阿贝尔群 ( B , + ) (B,+) (B,+) 的变换 f f f 是线性的,当且仅当对于所有 x , y ∈ A x,y \in A x,y∈A, 有 f ( x + y ) = f ( x ) + f ( y ) f(x+y)=f(x)+f(y) f(x+y)=f(x)+f(y)
- 仿射变换:仿射描述了从阿贝尔群 A A A,经过一次线性变换再加上一个平移,转换为另一个阿贝尔群 B B B 的过程。仿射变换 g g g 可表示为 g = f + b g = f+b g=f+b, b ∈ B b\in B b∈B 就是平移量。
- 非线性变换:对于非仿射的变换,可以被称为非线性变换。如 f ( x , y , z ) = x + y + x y z f(x,y,z)=x+y+xyz f(x,y,z)=x+y+xyz
3.2.3 有限域
有限域 G F ( p n ) GF(p^n) GF(pn) 亦称伽罗瓦域(galois field),是仅含有限个元素的域。密码学中使用有限域的好处,笔者总结了两点。
- 首先是对计算友好:计算机处理的是有限数据。在无限域中,数据有溢出的风险,而使用有限域数据最大不会超过 p n p^n pn
- 其次是增加系统安全性:很多现有密码学中的很多假设的强度都是和模数有关的。有限域加入模数后破解的困难和复杂性会陡然增加。反观无限域,攻击者可用数值逼近的方法破解加密函数。
有限域满足阿贝尔群对加法和乘法的定义。即:有限域对加法和乘法封闭,结合律和交换律成立,具有乘法幺元加法幺元,乘法逆元和加法负元。
一个有限域 G F ( p n ) GF(p^n) GF(pn) 有 p n p^n pn个元素,其中 p p p是一个素数, n n n 被称为素数的阶。一般在计算机领域令 p = 2 p=2 p=2 加法和乘法用模2加法和模2乘法。
G F ( p n ) GF(p^n) GF(pn) 中的元素必须在素域内。这个素域的定义类似于整数中的素数。如 x 4 + x 3 + x + 1 x^4+x^3+x+1 x4+x3+x+1 在 G F ( 2 ) GF(2) GF(2) 中而不是 G F ( 2 4 ) GF(2^4) GF(24)中,因为 x 4 + x 3 + x + 1 = ( x + 1 ) 2 ( x 2 + x + 1 ) x^4+x^3+x+1=(x+1)^2(x^2+x+1) x4+x3+x+1=(x+1)2(x2+x+1)
G F ( 2 8 ) GF(2^8) GF(28)是一个比较常用的有限域,8刚好是一个字节的比特数,我们对plaintext进行分块也是基于字节,AES算法的列混淆用的就是 G F ( 2 8 ) GF(2^8) GF(28) 的乘法。
G F ( 2 8 ) GF(2^8) GF(28)的经典性质有:模二乘法幺元为1,模二加法幺元为0,一共有 2 8 2^8 28 个元素。
笔者数学不是很好,如果对此感兴趣可以查看相关资料。
3.3 扩散和混淆
扩散(diffusion)和混淆(confusion)是密码学之父香农提出的设计密码体制的两种基本方法,其目的是为了抵抗对手对密码体制的统计分析.在分组密码的设计中,充分利用扩散和混淆,可以有效地抵抗对手从密文的统计特性推测明文或密钥.扩散和混淆是现代分组密码的设计基础。
-
扩散diffusion,就是让明文中的每一位影响密文中的许多位,这样可以隐蔽明文的统计特性。理想的加密应该使明文或密钥的少量变化会引起密文的很大变化,这种属性也被称为雪崩效应。
-
混淆confusion,就是将密文与密钥之间的统计关系变得尽可能复杂,使得对手即使获取了关于密文的一些统计特性,也无法推测密钥。理想的混淆应当有复杂的格式,每个密文比特位都是消息块比特位和密钥比特位的函数。
-
善用线性变换可以达到比较好的扩散效果,使用复杂的非线性变换可以达到比较好的混淆效果,乘积和迭代有助于实现扩散和混淆,上述法则几乎适用于所有的分组加密算法。
四、AES
4.1 DES(Data Encryption Standard)
DES是IBM在1976年为NBS开发的对称加密算法,在2000前一直作为标准的分组加密算法,直到2000年后被AES替换,它的密钥长度为56bits,第8、16、24、32、40、48、56、64 等8位是校验位,参与加密过程的密钥长度为56+8=64bits,块数据长度为64bits。由于DES密钥较短,所以容易被穷举键值攻击所破,需要更强大的加密算法才能保证数据的安全。
4.2 AES(The Advanced Encryption Standard)
AES加密即高级加密标注难,又称Rijndael加密,2001年发布并成为替代DES的标准分组加密算法。它的速度比Triple-DES快,效果也比Triple-DES好。
AES的文本分组长度128bits,密钥长度128/192/256bits,AES算法主要有四种操作,分别是:
- 字节代换(Substitue Bytes)
- 行移位(Shift Rows)
- 列混淆(Mix Column)
- 轮密钥加(Add Round Key)
AES通过重复多轮以上的算法进行加密,加密的轮数取决于不同的参数,如下表所示:
AES的流程如下图所示,我们可以看到,加密中的每个步骤都可以在解密过程中找到对应的逆操作,从而最后能还原文本。
4.2.1 字节代换(Substitue Bytes)
这一步是非线性变化(可增强混淆),128bits的数据对应16个字节 A 0 , A 1 , … , A 15 A_0, A_1,\dots,A_{15} A0,A1,…,A15,字节代换将每一个字节映射到另外一个字节 B 0 , B 1 , … , B 15 B_0, B_1,\dots,B_{15} B0,B1,…,B15,该过程是可逆的,代换关系表又被称为S-Box,每一个字节都是 G F ( 2 8 ) GF(2^8) GF(28) 中的元素。
S盒的数学意义是,求字节 A A A 在 G F ( 2 8 ) GF(2^8) GF(28)的逆元+一个仿射变换得到字节 B B B 。一般S盒会提前计算好,然后硬编码在程序的数组当中。
该步骤的逆过程是由
S
−
1
S^{-1}
S−1盒变换完成的。
4.2.2 行位移(Shift Rows)
这一步是简单的线性变换(增强扩散效果)。首先把输入字节变成一个4*4的矩阵,从上往下从左往右排序,然后第一行保持不动,第二行向左移一位,第三行向左移两位,第四行向左移三位,最后再从上往下,从左到右地读出数据。
下图的shift by x是右移x位的意思,但是右移x位等价于左移4-x位, 所以上面的描述和下图并不矛盾。
该步骤的逆向操作很简单,左移变右移就行了。
4.2.3 列混淆(Mix Column)
列混淆本质是一个矩阵乘法,将每四个字节进行混淆,用一个
C
C
C 矩阵与之进行
G
F
(
2
8
)
GF(2^8)
GF(28) 域上的相乘,然后模 00011011即可
(据说这个数是从
P
(
x
)
=
x
8
+
x
4
+
x
3
+
x
+
1
P(x)=x^8+x^4+x^3+x+1
P(x)=x8+x4+x3+x+1 得来的,是100011011,最高位的1被省略了)
C
=
[
02
03
01
01
01
02
03
01
01
01
02
03
03
01
01
02
]
C=\begin{bmatrix}02&03&01&01\\01&02&03&01\\01&01&02&03\\03&01&01&02\end{bmatrix}
C=⎣⎢⎢⎡02010103030201010103020101010302⎦⎥⎥⎤
[
O
0
,
0
O
0
,
1
O
0
,
2
O
0
,
3
O
1
,
0
O
1
,
1
O
1
,
2
O
1
,
3
O
2
,
0
O
2
,
1
O
2
,
2
O
2
,
3
O
3
,
0
O
3
,
1
O
3
,
2
O
3
,
3
]
=
C
[
I
0
,
0
I
0
,
1
I
0
,
2
I
0
,
3
I
1
,
0
I
1
,
1
I
1
,
2
I
1
,
3
I
2
,
0
I
2
,
1
I
2
,
2
I
2
,
3
I
3
,
0
I
3
,
1
I
3
,
2
I
3
,
3
]
\begin{bmatrix}O_{0,0}&O_{0,1}&O_{0,2}&O_{0,3}\\O_{1,0}&O_{1,1}&O_{1,2}&O_{1,3}\\O_{2,0}&O_{2,1}&O_{2,2}&O_{2,3}\\O_{3,0}&O_{3,1}&O_{3,2}&O_{3,3}\\\end{bmatrix}=C\begin{bmatrix}I_{0,0}&I_{0,1}&I_{0,2}&I_{0,3}\\I_{1,0}&I_{1,1}&I_{1,2}&I_{1,3}\\I_{2,0}&I_{2,1}&I_{2,2}&I_{2,3}\\I_{3,0}&I _{3,1}&I_{3,2}&I_{3,3}\\\end{bmatrix}
⎣⎢⎢⎡O0,0O1,0O2,0O3,0O0,1O1,1O2,1O3,1O0,2O1,2O2,2O3,2O0,3O1,3O2,3O3,3⎦⎥⎥⎤=C⎣⎢⎢⎡I0,0I1,0I2,0I3,0I0,1I1,1I2,1I3,1I0,2I1,2I2,2I3,2I0,3I1,3I2,3I3,3⎦⎥⎥⎤
这里举一个例子,假设输入数据的某一列为
[
C
9
6
E
46
A
6
]
T
\begin{bmatrix}C9&6E&46&A6\end{bmatrix}^T
[C96E46A6]T
逆向过程很简单,左乘一个 C − 1 C^{-1} C−1矩阵即可。
4.2.4 轮密钥加
这个步骤也比较简单,每一轮加密过程中,输入与轮密钥进行异或,解密时再异或该轮的轮密钥即可恢复。
AES算法中轮密钥是根据初始密钥和中间结果生成的。首先把128位初始密钥划分为16个字节,塞进4*4的矩阵中,然后每一列作为一个字,这个w就是由字组成的数组。每一轮都会基于上一轮的四个字
w
[
i
−
3
]
,
…
,
w
[
i
]
w[i-3], \dots, w[i]
w[i−3],…,w[i] 生成新的
w
[
i
+
1
]
,
…
,
w
[
i
+
4
]
w[i+1], \dots, w[i+4]
w[i+1],…,w[i+4]。这个变换如何实现呢?是通过下图的
g
g
g 函数实现的。
- 首先对字里面的元素进行位移,左移一位得到结果A
- 然后用S盒进行变换,得到结果B
- 计算A与B的异或,得到 g g g 的输出
然后用下图的方法就可以得到新一轮的字了。这个方法描述起来太麻烦了直接看图吧,嗯。。。
或者也可以参考这篇博客 :AES 轮密钥(子密钥如何生成)