源码是基于 FIPS PUB 197 标准开发的。关于FIPS PUB 197 标准详见《Federal InformationProcessing Standards Publication 197》文件,公众号后台回复 “AES加密 ”可获取。
1. 密钥扩展
如上文3.4章节介绍密钥扩展过程的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43/** * @brief Key Expansion * @param *key 密钥 * @param *w 密钥编排结果 * @retval */ void aes_key_expansion(uint8_t *key, uint8_t *w) { uint8_t tmp[4]; uint8_t i; uint8_t len = Nb*(Nr+1); //分组大小*(轮数+1) //1)将初始密钥以列为主,转化为4个32 bits的字,分别记为w[0…3] for (i = 0; i < Nk; i++) { w[4*i+0] = key[4*i+0]; w[4*i+1] = key[4*i+1]; w[4*i+2] = key[4*i+2]; w[4*i+3] = key[4*i+3]; } //2)依次求解w[i],其中j是整数并且属于[4,43];for (i = Nk; i < len; i++) { tmp[0] = w[4*(i-1)+0]; tmp[1] = w[4*(i-1)+1]; tmp[2] = w[4*(i-1)+2]; tmp[3] = w[4*(i-1)+3]; //3)若i%4=0,则w[i]=w[i-4]⊕g(w[i-1]),否则w[i]=w[i-4]⊕w[i-1];if (i%Nk == 0) { rot_word(tmp); //4)将w循环左移一个字节;sub_word(tmp); //5)分别对每个字节按S盒进行映射;coef_add(tmp, Rcon(i/Nk), tmp); //6)与32 bits的常量(RC[j/4],0,0,0)进行异或 } else if (Nk > 6 && i%Nk == 4) { sub_word(tmp); } w[4*i+0] = w[4*(i-Nk)+0]^tmp[0]; w[4*i+1] = w[4*(i-Nk)+1]^tmp[1]; w[4*i+2] = w[4*(i-Nk)+2]^tmp[2]; w[4*i+3] = w[4*(i-Nk)+3]^tmp[3]; } }
2. 加密过程
1)先得到到扩展密钥 W
2) 把128bit字符放进状态矩阵
3)对状态矩阵进行混淆 S = AddRoundKey(S, W0),
4)在执行Nr轮加密 (字节替换、行移位变换、列混合变换、轮密钥加变换)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47代码如下: /** * @brief Performs the AES cipher operation * @param *in 明文 * @param *out 加密后的密文 * @param *w 扩展后的密钥 * @retval */ void aes_cipher(uint8_t *in, uint8_t *out, uint8_t *w) { uint8_t state[4*Nb]; uint8_t r, i, j; //STEP2: 把128bit字符放进状态矩阵 for (i = 0; i < 4; i++) { for (j = 0; j < Nb; j++) { state[Nb*i+j] = in[i+4*j]; } } //STEP3: 对状态矩阵进行混淆 add_round_key(state, w, 0); //STEP4: 在执行完Nr轮加密 for (r = 1; r < Nr; r++) { sub_bytes(state); //字节替换 shift_rows(state); //行移位变换 mix_columns(state); //列混合变换 add_round_key(state, w, r); //轮密钥加变换 } sub_bytes(state); shift_rows(state); add_round_key(state, w, Nr); for (i = 0; i < 4; i++) { for (j = 0; j < Nb; j++) { out[i+4*j] = state[Nb*i+j]; } } }
3. 解密过程
解密函数中调用的是各轮操作的逆函数。代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38/** * @brief Performs the AES inverse cipher operation * @param *in 密文 * @param *out 密文的逆 * @param *w 扩展后的密钥 * @retval */ void aes_inv_cipher(uint8_t *in, uint8_t *out, uint8_t *w) { uint8_t state[4*Nb]; uint8_t r, i, j; for (i = 0; i < 4; i++) { for (j = 0; j < Nb; j++) { state[Nb*i+j] = in[i+4*j]; } } add_round_key(state, w, Nr); for (r = Nr-1; r >= 1; r--) { inv_shift_rows(state); inv_sub_bytes(state); add_round_key(state, w, r); inv_mix_columns(state); } inv_shift_rows(state); inv_sub_bytes(state); add_round_key(state, w, 0); for (i = 0; i < 4; i++) { for (j = 0; j < Nb; j++) { out[i+4*j] = state[Nb*i+j]; } } }
4. API介绍
- AddRoundKey()
加密和解密中使用的变换,将一个轮密钥异或到状态上。轮密钥的长度等于状态的大小(即对于 Nb=4, 轮密钥长度等于128bits/16bytes)
- MixColumns()
加密中使用的变换,以状态的每一列作为输入,混合每一列的数据(彼此独立的)得到新的列。
- Rcon[]
密钥扩展算法中用到的轮常数
- RotWord()
密钥扩展算法中使用的函数,对 4-byte 字进行循环移位
- ShiftRows()
加密中使用的变换, 将状态的最后 3 行循环移动不同的位移量
- SubBytes()
加密中使用的变换,利用一个非线性字节替代表(S 盒),独立地对状态的每个字节进行操作
- SubWord()
密钥扩展算法中使用的函数,它以 4-byte 字作为输入,对于 4 字节中的每一字节分别应用 S 盒,得到一个输出字
- AddRoundKey()
加密和解密中使用的变换,将一个轮密钥异或到状态上。轮密钥的长度等于状态的大小(即对于 Nb=4, 轮密钥长度等于128bits/16bytes)
- InvMixColumns()
解密中使用的变换, MixColumns()的逆变换
- InvShiftRows()
解密中使用的变换, ShiftRows()的逆变换
- InvSubBytes()
解密中使用的变换, SubBytes()的逆变换
更多详细介绍详见代码目录下我用Doxygen软件制作的 index.html 文件
基于 Cortex-M3 完整的程序代码 公众号后台回复 “ AES加密 ” 获取。
阅读原文
最后
以上就是积极篮球最近收集整理的关于安全算法-AES 加密算法源码解析的全部内容,更多相关安全算法-AES内容请搜索靠谱客的其他文章。
发表评论 取消回复