其中FFmul为有限域GF(28)上的乘法,标准算法应该是循环8次(b与a的每一位相乘,结果相加),但这里只用到最低2位,解密时用到的逆列混淆也只用了低4位,所以在这里高4位的运算是多余的,只计算低4位。
AddRoundKey(轮密钥加变换)
简单来说就是逐字节相加,有限域GF(28)上的加法是模2加法,即异或
void AES::AddRoundKey(unsigned char state[][4], unsigned char k[][4]) {
int r,c;
for(c=0; c<4; c++) {
for(r=0; r<4; r++) {
state[r][c] ^= k[r][c]; } } }
KeyExpansion(密钥扩展)
将输入的密钥扩展为11组128位密钥组,其中第0组为输入密钥本身 其后第n组第i列 为 第n-1组第i列 与 第n组第i-1列之和(模2加法,1<= i <=3)
对于每一组 第一列即i=0,有特殊的处理
将前一列即第n-1组第3列的4个字节循环左移1个字节, 并对每个字节进行字节替代变换SubBytes 将第一行(即第一个字节)与轮常量rc[n]相加 最后再与前一组该列相加
void AES::KeyExpansion(unsigned char* key, unsigned char w[][4][4]) {
int i,j,r,c;
unsigned char rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; for(r=0; r<4; r++) {
for(c=0; c<4; c++) {
w[0][r][c] = key[r+c*4]; } }
for(i=1; i<=10; i++) {
for(j=0; j<4; j++) {
unsigned char t[4]; for(r=0; r<4; r++) {
t[r] = j ? w[i][r][j-1] : w[i-1][r][3]; }
if(j == 0) {
unsigned char temp = t[0]; for(r=0; r<3; r++) {
t[r] = Sbox[t[(r+1)%4]]; }
t[3] = Sbox[temp]; t[0] ^= rc[i-1]; }
for(r=0; r<4; r++) {
w[i][r][j] = w[i-1][r][j] ^ t[r]; } } } }
解密的基本运算
AES解密算法与加密不同,基本运算中除了AddRoundKey(轮密钥加)不变外,其余的都需要进行逆变换,即
InvSubBytes(逆字节替代)、InvShiftRows(逆行移位)、InvMixColumns(逆列混淆)