逆向算法之AES算法
AES加密算法是典型的对称加密算法,对称加密算法也就是加密和解密用相同的密钥。
AES加密数组块分组长度必须为128比特,密钥长度可以是128比特、192比特、256比特中的任意一个。AES加密有很多轮的重复和变换,步骤是1、密钥扩展,2、初始轮,3、重复轮,4、最终轮。
1、字节代换
AES的字节代换是一个简单的查表操作,AES定义了一个s盒和一个逆s盒。
状态矩阵中的元素按照将字节的高4位作为行值,低四位作为列值,取出s盒或者逆s盒中对应的行的元素作为输出。例如,加密时,输出的字节s1为0x12,则查s盒的第0x01行和0x02列,得到值0xc9,然后替换s1原有的0x12为0xc9。逆s盒如下。
2、行移位
行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节。
3、列混合操作
列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵。
4、轮密钥加
轮密钥加是将128位轮密钥Ki同状态矩阵中的数据进行逐位异或操作。
AES算法实现
1、密钥拓展的实现
//密钥对应的扩展数组 static int w[44]; /** * 扩展密钥,结果是把w[44]中的每个元素初始化 */ static void extendKey(char *key) { for(int i = 0; i < 4; i++) w[i] = getWordFromStr(key + i * 4); for(int i = 4, j = 0; i < 44; i++) { if( i % 4 == 0) { w[i] = w[i - 4] ^ T(w[i - 1], j); j++;//下一轮 }else { w[i] = w[i - 4] ^ w[i - 1]; } } }
/** * 常量轮值表 */ static const int Rcon[10] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000 }; /** * 密钥扩展中的T函数 */ static int T(int num, int round) { int numArray[4]; splitIntToArray(num, numArray); leftLoop4int(numArray, 1);//字循环 //字节代换 for(int i = 0; i < 4; i++) numArray[i] = getNumFromSBox(numArray[i]); int result = mergeArrayToInt(numArray); return result ^ Rcon[round]; } ———————————————— 版权声明:本文为CSDN博主「TimeShatter」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_28205153/article/details/55798628
/** * 常量轮值表 */ static const int Rcon[10] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000 }; /** * 密钥扩展中的T函数 */ static int T(int num, int round) { int numArray[4]; splitIntToArray(num, numArray); leftLoop4int(numArray, 1);//字循环 //字节代换 for(int i = 0; i < 4; i++) numArray[i] = getNumFromSBox(numArray[i]); int result = mergeArrayToInt(numArray); return result ^ Rcon[round]; }
2、字节代换的实现
/** * 根据索引,从S盒中获得元素 */ static int getNumFromSBox(int index) { int row = getLeft4Bit(index); int col = getRight4Bit(index); return S[row][col]; } /** * 字节代换 */ static void subBytes(int array[4][4]){ for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) array[i][j] = getNumFromSBox(array[i][j]); }
3、行移位的实现
/** * 将数组中的元素循环左移step位 */ static void leftLoop4int(int array[4], int step) { int temp[4]; for(int i = 0; i < 4; i++) temp[i] = array[i]; int index = step % 4 == 0 ? 0 : step % 4; for(int i = 0; i < 4; i++){ array[i] = temp[index]; index++; index = index % 4; } } /** * 行移位 */
static void shiftRows(int array[4][4]) {
int rowTwo[4], rowThree[4], rowFour[4];
//复制状态矩阵的第2,3,4行
for(int i = 0; i < 4; i++) {
rowTwo[i] = array[1][i];
rowThree[i] = array[2][i];
rowFour[i] = array[3][i];
}
//循环左移相应的位数
leftLoop4int(rowTwo, 1);
leftLoop4int(rowThree, 2);
leftLoop4int(rowFour, 3);
//把左移后的行复制回状态矩阵中
for(int i = 0; i < 4; i++) {
array[1][i] = rowTwo[i];
array[2][i] = rowThree[i];
array[3][i] = rowFour[i];
}
}
4、列混合的实现
/** * 列混合要用到的矩阵 */ static const int colM[4][4] = { 2, 3, 1, 1, 1, 2, 3, 1, 1, 1, 2, 3, 3, 1, 1, 2 }; static int GFMul2(int s) { int result = s << 1; int a7 = result & 0x00000100; if(a7 != 0) { result = result & 0x000000ff; result = result ^ 0x1b; } return result; } static int GFMul3(int s) { return GFMul2(s) ^ s; } /** * GF上的二元运算 */ static int GFMul(int n, int s) { int result; if(n == 1) result = s; else if(n == 2) result = GFMul2(s); else if(n == 3) result = GFMul3(s); else if(n == 0x9) result = GFMul9(s); else if(n == 0xb)//11 result = GFMul11(s); else if(n == 0xd)//13 result = GFMul13(s); else if(n == 0xe)//14 result = GFMul14(s); return result; } /** * 列混合 */ static void mixColumns(int array[4][4]) { int tempArray[4][4]; for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) tempArray[i][j] = array[i][j]; for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++){ array[i][j] = GFMul(colM[i][0],tempArray[0][j]) ^ GFMul(colM[i][1],tempArray[1][j]) ^ GFMul(colM[i][2],tempArray[2][j]) ^ GFMul(colM[i][3], tempArray[3][j]); } }
5、轮密钥加的实现
/** * 轮密钥加 */ static void addRoundKey(int array[4][4], int round) { int warray[4]; for(int i = 0; i < 4; i++) { splitIntToArray(w[ round * 4 + i], warray); for(int j = 0; j < 4; j++) { array[j][i] = array[j][i] ^ warray[j]; } } }
总AES解密函数
/** * 参数 c: 密文的字符串数组。 * 参数 clen: 密文的长度。 * 参数 key: 密钥的字符串数组。 */ void deAes(char *c, int clen, char *key) { int keylen = strlen(key); if(clen == 0 || clen % 16 != 0) { printf("密文字符长度必须为16的倍数!现在的长度为%d\n",clen); exit(0); } if(!checkKeyLen(keylen)) { printf("密钥字符长度错误!长度必须为16、24和32。当前长度为%d\n",keylen); exit(0); } extendKey(key);//扩展密钥 int cArray[4][4]; for(int k = 0; k < clen; k += 16) { convertToIntArray(c + k, cArray); addRoundKey(cArray, 10); int wArray[4][4]; for(int i = 9; i >= 1; i--) { deSubBytes(cArray); deShiftRows(cArray); deMixColumns(cArray); getArrayFrom4W(i, wArray); deMixColumns(wArray); addRoundTowArray(cArray, wArray); } deSubBytes(cArray); deShiftRows(cArray); addRoundKey(cArray, 0); convertArrayToStr(cArray, c + k); } }