逆向算法之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);

    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM