源码是基于 FIPS PUB 197 标准开发的。关于FIPS PUB 197 标准详见《Federal InformationProcessing Standards Publication 197》文件,
1. 密钥扩展
如上文3.4章节介绍密钥扩展过程的代码如下:
/**
* @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轮加密 (字节替换、行移位变换、列混合变换、轮密钥加变换)
代码如下:
/**
* @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. 解密过程
解密函数中调用的是各轮操作的逆函数。代码如下:
/**
* @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 完整的程序代码