文章目录
1、AES算法简介
AES算法是一种对称加密算法,也是一种分组加密算法,AES根据密钥长度不同可以细分为AES128,AES192和AES256,同时和DES一样具有多种工作模式,我们只实现ECB即可,至于填充方式我们使用PKCS7。
2、AES加密步骤
2.1 消息填充
把输入的
L
L
L长明文
M
M
M填充至128比特的整数倍,即
L
+
k
∗
8
=
0
m
o
d
128
L + k * 8 = 0\ mod\ 128
L+k∗8=0 mod 128
填充内容是以1字节表示的消息长度,填充
k
k
k个字节。
填充完后,对消息每一块进行加密时,我们是吧每一块当做一个4*4字节的二维数组矩阵表示,例如把"1234567890abcdef"放入矩阵中,对应图如下
2.2 密钥扩展
对密钥的扩展也是对一个矩阵进行扩展,不过128是一个4*4矩阵,192是一个4*6矩阵,256是一个4*8矩阵,以128的举例,我们会把密钥竖着排列得到一个矩阵,每一列作为一轮密钥,列数称为 N k Nk Nk,然后我们根据初始的密钥进行密钥扩展,扩展至 ( N r + 1 ) ∗ 4 (Nr+1)*4 (Nr+1)∗4个密钥,得到 W W W,其中 N r Nr Nr与 N k Nk Nk对应关系如下
Nk | Nr |
---|---|
4 | 10 |
6 | 12 |
8 | 14 |
以128的AES举例,密钥扩展到 W W W如下
整体
W
W
W扩展规则如下
W
[
i
]
=
{
k
e
y
[
i
]
0
≤
i
<
N
k
W
[
i
−
N
k
]
⊕
T
(
W
[
i
−
1
]
,
i
/
N
k
)
i
m
o
d
N
k
=
0
W
[
i
−
N
k
]
⊕
SubWord
(
W
[
i
−
1
]
)
N
k
>
6
&
i
m
o
d
N
k
=
4
W
[
i
−
N
k
]
⊕
W
[
i
−
1
]
e
l
s
e
W[i] = \begin{cases} key[i] \quad \ 0 ≤ i < Nk\\ W[i-Nk] \oplus \text{T}(W[i-1], i/Nk) & \ i \mod Nk = 0 \\ W[i-Nk] \oplus \text{SubWord}(W[i-1]) & \ Nk>6 \ \& \ i \mod Nk=4 \\ W[i-Nk] \oplus W[i-1] & else \end{cases}
W[i]=⎩
⎨
⎧key[i] 0≤i<NkW[i−Nk]⊕T(W[i−1],i/Nk)W[i−Nk]⊕SubWord(W[i−1])W[i−Nk]⊕W[i−1] imodNk=0 Nk>6 & imodNk=4else
其中
T
T
T函数是
T
=
SubWord
(
RotWord
(
W
[
i
−
1
]
)
)
⊕
R
C
O
N
[
r
o
u
n
d
]
<
<
24
T = \text{SubWord}(\text{RotWord}(W[i-1])) \oplus RCON[round] << 24
T=SubWord(RotWord(W[i−1]))⊕RCON[round]<<24
R
o
t
W
o
r
d
RotWord
RotWord是左循环一位,
S
u
b
W
o
r
d
SubWord
SubWord是字节替换,
R
C
O
N
RCON
RCON是一个常量
2.3 轮密钥加
单纯的消息块与密钥进行对应异或。
2.4 字节替换
利用S盒进行对应替换。
2.5 行移位
对消息块,第一行不移动,第二行循环左移1个字节,第三行循环左移2字节,第四行循环左移3字节。
2.6 列混淆
将消息块与矩阵相乘
[ b 0 , 0 b 0 , 1 b 0 , 2 b 0 , 3 b 1 , 0 b 1 , 1 b 1 , 2 b 1 , 3 b 2 , 0 b 2 , 1 b 2 , 2 b 2 , 3 b 3 , 0 b 3 , 1 b 3 , 2 b 3 , 3 ] = [ 2 3 1 1 1 2 1 1 1 1 2 3 3 1 3 2 ] [ a 0 , 0 a 0 , 1 a 0 , 2 a 0 , 3 a 1 , 0 a 1 , 1 a 1 , 2 a 1 , 3 a 2 , 0 a 2 , 1 a 2 , 2 a 2 , 3 a 3 , 0 a 3 , 1 a 3 , 2 a 3 , 3 ] \begin{bmatrix} b_{0,0} & b_{0,1} & b_{0,2} & b_{0,3} \\ b_{1,0} & b_{1,1} & b_{1,2} & b_{1,3} \\ b_{2,0} & b_{2,1} & b_{2,2} & b_{2,3} \\ b_{3,0} & b_{3,1} & b_{3,2} & b_{3,3} \\ \end{bmatrix} =\begin{bmatrix} 2 & 3 & 1 & 1 \\ 1 & 2 & 1 & 1 \\ 1 & 1 & 2 & 3 \\ 3 & 1 & 3 & 2 \\ \end{bmatrix} \begin{bmatrix} a_{0,0} & a_{0,1} & a_{0,2} & a_{0,3} \\ a_{1,0} & a_{1,1} & a_{1,2} & a_{1,3} \\ a_{2,0} & a_{2,1} & a_{2,2} & a_{2,3} \\ a_{3,0} & a_{3,1} & a_{3,2} & a_{3,3} \\ \end{bmatrix} b0,0b1,0b2,0b3,0b0,1b1,1b2,1b3,1b0,2b1,2b2,2b3,2b0,3b1,3b2,3b3,3 = 2113321111231132 a0,0a1,0a2,0a3,0a0,1a1,1a2,1a3,1a0,2a1,2a2,2a3,2a0,3a1,3a2,3a3,3
我们写代码使用 X T i m e XTime XTime乘法更加便捷
{ b 0 , j = X T i m e ( a 0 , j ) ⊕ X T i m e ( a 1 , j ) ⊕ a 1 , j ⊕ a 2 , j ⊕ a 3 , j b 1 , j = a 0 , j ⊕ X T i m e ( a 1 , j ) ⊕ X T i m e ( a 2 , j ) ⊕ a 2 , j ⊕ a 3 , j b 2 , j = a 0 , j ⊕ a 1 , j ⊕ X T i m e ( a 2 , j ) ⊕ X T i m e ( a 3 , j ) ⊕ a 3 , j b 3 , j = X T i m e ( a 0 , j ) ⊕ a 0 , j ⊕ a 1 , j ⊕ a 2 , j ⊕ X T i m e ( a 3 , j ) \begin{cases} b_{0,j} = XTime(a_{0,j}) \oplus XTime(a_{1,j}) \oplus a_{1,j} \oplus a_{2,j} \oplus a_{3,j}\\ b_{1,j} = a_{0,j} \oplus XTime(a_{1,j}) \oplus XTime(a_{2,j}) \oplus a_{2,j} \oplus a_{3,j}\\ b_{2,j} = a_{0,j} \oplus a_{1,j} \oplus XTime(a_{2,j}) \oplus XTime(a_{3,j}) \oplus a_{3,j}\\ b_{3,j} = XTime(a_{0,j}) \oplus a_{0,j} \oplus a_{1,j} \oplus a_{2,j} \oplus XTime(a_{3,j})\\ \end{cases} ⎩ ⎨ ⎧b0,j=XTime(a0,j)⊕XTime(a1,j)⊕a1,j⊕a2,j⊕a3,jb1,j=a0,j⊕XTime(a1,j)⊕XTime(a2,j)⊕a2,j⊕a3,jb2,j=a0,j⊕a1,j⊕XTime(a2,j)⊕XTime(a3,j)⊕a3,jb3,j=XTime(a0,j)⊕a0,j⊕a1,j⊕a2,j⊕XTime(a3,j)
这里还要强调一下逆列混淆,要乘另外一个矩阵
[
b
0
,
0
b
0
,
1
b
0
,
2
b
0
,
3
b
1
,
0
b
1
,
1
b
1
,
2
b
1
,
3
b
2
,
0
b
2
,
1
b
2
,
2
b
2
,
3
b
3
,
0
b
3
,
1
b
3
,
2
b
3
,
3
]
=
[
0
E
0
B
0
D
09
09
0
E
0
B
0
D
0
D
09
0
E
0
B
0
B
0
D
09
0
E
]
[
a
0
,
0
a
0
,
1
a
0
,
2
a
0
,
3
a
1
,
0
a
1
,
1
a
1
,
2
a
1
,
3
a
2
,
0
a
2
,
1
a
2
,
2
a
2
,
3
a
3
,
0
a
3
,
1
a
3
,
2
a
3
,
3
]
\begin{bmatrix} b_{0,0} & b_{0,1} & b_{0,2} & b_{0,3} \\ b_{1,0} & b_{1,1} & b_{1,2} & b_{1,3} \\ b_{2,0} & b_{2,1} & b_{2,2} & b_{2,3} \\ b_{3,0} & b_{3,1} & b_{3,2} & b_{3,3} \\ \end{bmatrix} = \begin{bmatrix} 0E & 0B & 0D & 09 \\ 09 & 0E & 0B & 0D \\ 0D & 09 & 0E & 0B \\ 0B & 0D & 09 & 0E \\ \end{bmatrix} \begin{bmatrix} a_{0,0} & a_{0,1} & a_{0,2} & a_{0,3} \\ a_{1,0} & a_{1,1} & a_{1,2} & a_{1,3} \\ a_{2,0} & a_{2,1} & a_{2,2} & a_{2,3} \\ a_{3,0} & a_{3,1} & a_{3,2} & a_{3,3} \\ \end{bmatrix}
b0,0b1,0b2,0b3,0b0,1b1,1b2,1b3,1b0,2b1,2b2,2b3,2b0,3b1,3b2,3b3,3
=
0E090D0B0B0E090D0D0B0E09090D0B0E
a0,0a1,0a2,0a3,0a0,1a1,1a2,1a3,1a0,2a1,2a2,2a3,2a0,3a1,3a2,3a3,3
实现这个过程最好使用伽罗华域的二元运算,即
G
M
u
l
GMul
GMul运算
{
b
0
,
j
=
G
M
u
l
(
0
E
,
a
0
,
j
)
⊕
G
M
u
l
(
0
B
,
a
0
,
j
)
⊕
G
M
u
l
(
0
D
,
a
0
,
j
)
⊕
G
M
u
l
(
09
,
a
0
,
j
)
b
1
,
j
=
G
M
u
l
(
09
,
a
0
,
j
)
⊕
G
M
u
l
(
0
E
,
a
0
,
j
)
⊕
G
M
u
l
(
0
B
,
a
0
,
j
)
⊕
G
M
u
l
(
0
D
,
a
0
,
j
)
b
2
,
j
=
G
M
u
l
(
0
D
,
a
0
,
j
)
⊕
G
M
u
l
(
09
,
a
0
,
j
)
⊕
G
M
u
l
(
0
E
,
a
0
,
j
)
⊕
G
M
u
l
(
0
B
,
a
0
,
j
)
b
3
,
j
=
G
M
u
l
(
0
B
,
a
0
,
j
)
⊕
G
M
u
l
(
0
D
,
a
0
,
j
)
⊕
G
M
u
l
(
09
,
a
0
,
j
)
⊕
G
M
u
l
(
0
E
,
a
0
,
j
)
\begin{cases} b_{0,j} = GMul(0E,a_{0,j}) \oplus GMul(0B,a_{0,j}) \oplus GMul(0D,a_{0,j}) \oplus GMul(09,a_{0,j})\\ b_{1,j} = GMul(09,a_{0,j}) \oplus GMul(0E,a_{0,j}) \oplus GMul(0B,a_{0,j}) \oplus GMul(0D,a_{0,j})\\ b_{2,j} = GMul(0D,a_{0,j}) \oplus GMul(09,a_{0,j}) \oplus GMul(0E,a_{0,j}) \oplus GMul(0B,a_{0,j})\\ b_{3,j} = GMul(0B,a_{0,j}) \oplus GMul(0D,a_{0,j}) \oplus GMul(09,a_{0,j}) \oplus GMul(0E,a_{0,j})\\ \end{cases}
⎩
⎨
⎧b0,j=GMul(0E,a0,j)⊕GMul(0B,a0,j)⊕GMul(0D,a0,j)⊕GMul(09,a0,j)b1,j=GMul(09,a0,j)⊕GMul(0E,a0,j)⊕GMul(0B,a0,j)⊕GMul(0D,a0,j)b2,j=GMul(0D,a0,j)⊕GMul(09,a0,j)⊕GMul(0E,a0,j)⊕GMul(0B,a0,j)b3,j=GMul(0B,a0,j)⊕GMul(0D,a0,j)⊕GMul(09,a0,j)⊕GMul(0E,a0,j)
3、代码实现
创建AES类
public class AES{}
明文要以4*4字节矩阵存储,使用的byte
二维数组,密钥便以byte
一维数组存储。
3.1 参数准备
//常量
private static final int[] RCON = {
0x00,//占位
0x01, 0x02, 0x04, 0x08, 0x10,
0x20, 0x40, 0x80, 0x1B, 0x36
};
//S盒
private static final int[] S = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};
//逆S盒
private static final int[] INV_S = {
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
};
3.2 工具函数准备
//转换函数
private static byte[][] SHIFT(byte[] in) {
byte[][] out = new byte[4][4];
for (int i = 0;i < 16;i++) {
out[i % 4][i / 4] = in[i];
}
return out;
}
//逆转换
private static byte[] INV_SHIFT(byte[][] in) {
byte[] out = new byte[16];
for (int i = 0;i < 16;i++) {
out[i] = in[i % 4][i / 4];
}
return out;
}
//T函数
private static int T(int word,int round) {
return SubWord(RotWord(word)) ^ (RCON[round] << 24);
}
//32位字节S盒代换
private static int SubWord(int word) {
int b0 = S[(word >>> 24) & 0xFF];
int b1 = S[(word >>> 16) & 0xFF];
int b2 = S[(word >>> 8) & 0xFF];
int b3 = S[word & 0xFF];
return (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
}
//32位字节循环移位
private static int RotWord(int word) {
return (word << 8) | ((word >>> 24) & 0xFF);
}
//XTime运算
private static byte XTime(byte x) {
return (byte) ((x << 1) ^ (((x >>> 17) & 1) * 0x1B));
}
//乘法函数
private static byte MUL(byte a,int b) {
int aa = a & 0xFF; // 保证无符号运算
int bb = b & 0xFF;
int p = 0;
for (int i = 0; i < 8; i++) {
if ((bb & 0x01) != 0) p ^= aa;
boolean highBitSet = (aa & 0x80) != 0;
aa = (aa << 1) & 0xFF;
if (highBitSet) aa ^= 0x1B;
bb >>= 1;
}
return (byte) p;
}
3.3 密钥扩展
private int[] KeyExpansion(byte[] key,int Nk,int Nr) {
//获取轮密钥
int[] W = new int[4 * (Nr + 1)];
//赋值已有密钥
for (int i = 0;i < Nk;i++) {
W[i] = ((key[4 * i] & 0xFF) << 24) |
((key[4 * i + 1] & 0xFF) << 16) |
((key[4 * i + 2] & 0xFF) << 8) |
(key[4 * i + 3] & 0xFF);
}
//生成剩下的密钥
for (int i = Nk;i < W.length;i++) {
int temp = W[i - 1];
if (i % Nk == 0) temp = T(temp,i / Nk);
else if (Nk > 6 && (i % Nk == 4)) temp = SubWord(temp);
W[i] = W[i - Nk] ^ temp;
}
return W;
}
3.4 轮密钥加
private void AddRoundKey(byte[][] state,int[] W,int round) {
for (int col = 0;col < 4;col++) {
int word = W[round * 4 + col];
state[0][col] ^= (byte) ((word >>> 24) & 0xFF);
state[1][col] ^= (byte) ((word >>> 16) & 0xFF);
state[2][col] ^= (byte) ((word >>> 8) & 0xFF);
state[3][col] ^= (byte) (word & 0xFF);
}
}
3.3 字节替换和逆字节替换
//字节替换
private void SubBytes(byte[][] state) {
for (int row = 0;row < 4;row++) {
for (int col = 0;col < 4;col++) {
state[row][col] = (byte) (S[state[row][col] & 0xFF] & 0xFF);
}
}
}
//逆字节替换
private void InvSubBytes(byte[][] state) {
for (int row = 0;row < 4;row++) {
for (int col = 0;col < 4;col++) {
state[row][col] = (byte) (INV_S[state[row][col] & 0xFF] & 0xFF);
}
}
}
3.4 行移位和逆行移位
//行移位
private void ShiftRows(byte[][] state) {
//左移1位
byte temp = state[1][0];
for (int i = 0;i < 3;i++) {
state[1][i] = state[1][i + 1];
}
state[1][3] = temp;
//左移2位
byte t1 = state[2][0],t2 = state[2][1];
state[2][0] = state[2][2];
state[2][1] = state[2][3];
state[2][2] = t1;
state[2][3] = t2;
//左移3位(右移1位)
temp = state[3][3];
for (int i = 3;i > 0;i--) {
state[3][i] = state[3][i - 1];
}
state[3][0] = temp;
}
//逆行移位
private void InvShiftRows(byte[][] state) {
//右移1位
byte temp = state[1][3];
for (int i = 3; i > 0; i--) {
state[1][i] = state[1][i - 1];
}
state[1][0] = temp;
//右移2位
byte t1 = state[2][0], t2 = state[2][1];
state[2][0] = state[2][2];
state[2][1] = state[2][3];
state[2][2] = t1;
state[2][3] = t2;
//右移3位
temp = state[3][0];
for (int i = 0; i < 3; i++) {
state[3][i] = state[3][i + 1];
}
state[3][3] = temp;
}
3.5 列混淆和逆列混淆
//列混淆
private void MixColumns(byte[][] state) {
//使用XTime函数计算
for (int col = 0;col < 4;col++) {
byte s0 = state[0][col];
byte s1 = state[1][col];
byte s2 = state[2][col];
byte s3 = state[3][col];
state[0][col] = (byte) (XTime(s0) ^ XTime(s1) ^ s1 ^ s2 ^ s3);
state[1][col] = (byte) (s0 ^ XTime(s1) ^ XTime(s2) ^ s2 ^ s3);
state[2][col] = (byte) (s0 ^ s1 ^ XTime(s2) ^ XTime(s3) ^ s3);
state[3][col] = (byte) (XTime(s0) ^ s0 ^ s1 ^ s2 ^ XTime(s3));
}
}
//逆列混淆
private void InvMixColumns(byte[][] state) {
//使用MUL函数计算
for (int col = 0; col < 4; col++) {
byte s0 = state[0][col];
byte s1 = state[1][col];
byte s2 = state[2][col];
byte s3 = state[3][col];
state[0][col] = (byte) (MUL(s0, 0x0e) ^ MUL(s1, 0x0b) ^ MUL(s2, 0x0d) ^ MUL(s3, 0x09));
state[1][col] = (byte) (MUL(s0, 0x09) ^ MUL(s1, 0x0e) ^ MUL(s2, 0x0b) ^ MUL(s3, 0x0d));
state[2][col] = (byte) (MUL(s0, 0x0d) ^ MUL(s1, 0x09) ^ MUL(s2, 0x0e) ^ MUL(s3, 0x0b));
state[3][col] = (byte) (MUL(s0, 0x0b) ^ MUL(s1, 0x0d) ^ MUL(s2, 0x09) ^ MUL(s3, 0x0e));
}
}
3.6 加密函数
public byte[] Encrypt(byte[] msg,byte[] key) {
int keyLength = key.length;
//根据密钥长度不同,处理不同
int Nk,Nr;
if (keyLength == 16) {
Nk = 4;Nr = 10;
} else if (keyLength == 24) {
Nk = 6;Nr = 12;
} else if (keyLength == 32) {
Nk = 8;Nr = 14;
} else {
throw new IllegalArgumentException("密钥长度错误");
}
//使用PKCS7填充
int paddingLength = 16 - (msg.length % 16);
byte[] paddedMsg = new byte[msg.length + paddingLength];
System.arraycopy(msg, 0, paddedMsg, 0, msg.length);
// 填充 paddingLength 个值为 paddingLength 的字节
for (int i = msg.length; i < paddedMsg.length; i++) {
paddedMsg[i] = (byte) paddingLength;
}
int n = paddedMsg.length / 16;
//获取轮密钥
int[] W = KeyExpansion(key,Nk,Nr);
byte[] C = new byte[n * 16];
//对每块操作
for (int i = 0;i < n;i++) {
byte[] block = Arrays.copyOfRange(paddedMsg,i * 16,(i + 1) * 16);
byte[][] blockA = SHIFT(block);
AddRoundKey(blockA,W,0);
for (int j = 1;j < Nr;j++) {
SubBytes(blockA);
ShiftRows(blockA);
MixColumns(blockA);
AddRoundKey(blockA,W,j);
}
SubBytes(blockA);
ShiftRows(blockA);
AddRoundKey(blockA,W,Nr);
System.arraycopy(INV_SHIFT(blockA),0,C,i * 16,16);
}
return C;
}
3.7 解密函数
public byte[] Decrypt(byte[] msg,byte[] key) {
int keyLength = key.length;
int Nk,Nr;
if (keyLength == 16) {
Nk = 4;Nr = 10;
} else if (keyLength == 24) {
Nk = 6;Nr = 12;
} else if (keyLength == 32) {
Nk = 8;Nr = 14;
} else {
throw new IllegalArgumentException("密钥长度错误");
}
int n = msg.length / 16;
byte[] paddedMsg = new byte[n * 16];
System.arraycopy(msg,0,paddedMsg,0,msg.length);
int[] W = KeyExpansion(key,Nk,Nr);
byte[] M = new byte[n * 16];
for (int i = 0;i < n;i++) {
byte[] block = Arrays.copyOfRange(paddedMsg,i * 16,(i + 1) * 16);
byte[][] blockA = SHIFT(block);
AddRoundKey(blockA,W,Nr);
for (int j = Nr - 1;j >= 1;j--) {
InvShiftRows(blockA);
InvSubBytes(blockA);
AddRoundKey(blockA,W,j);
InvMixColumns(blockA);
}
InvShiftRows(blockA);
InvSubBytes(blockA);
AddRoundKey(blockA,W,0);
System.arraycopy(INV_SHIFT(blockA),0,M,i * 16,16);
}
// 去除 PKCS#7 填充
int padding = M[M.length - 1] & 0xFF;
if (padding <= 0 || padding > 16) throw new IllegalArgumentException("填充长度不对");
// 验证填充是否一致
for (int i = M.length - padding; i < M.length; i++) {
if ((M[i] & 0xFF) != padding) {
throw new IllegalArgumentException("填充错误");
}
}
return Arrays.copyOf(M, M.length - padding);
}
4、结果验证
4.1 加密解密验证-128
测试数据
{
"msg":"00112233445566778899aabbccddeeff",
"key":"2b7e151628aed2a6abf7158809cf4f3c"
}
结果
验证
解密
4.2 加密解密验证-192
测试数据
{
"msg":"00112233445566778899aabbccddeeff",
"key":"8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"
}
结果
验证
解密
4.3 加密解密验证-256
测试数据
{
"msg":"00112233445566778899aabbccddeeff",
"key":"603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"
}
结果
结果验证
解密
证明AES成功实现
5、后记
本篇文章参考了