AES实现C语言

C语言AES

新手!内容代码转自AES加密算法的详细介绍与实现,我只是在此基础上做了注释,留给自己看

有些代码我也没看懂,所以还请大家多多指教,带?的是我不明白的

!!!注意,因为本身代码转自他人的,所以我在人家原有的基础上还做了注释,为了便于分辨,我写的注释前有一个“-”!!!
比如
在这里插入图片描述

  • 整体
    首先判断明文、密钥长度是否符合要求
    然后扩展密钥【扩到44个】
    第0轮 ,①明文矩阵转化为状态矩阵②轮密钥加
    第1-9轮 ,①字节代换②行移位③列混合④轮密钥加
    第10轮 ,①字节代换②行移位③轮密钥加④状态矩阵转化为密文矩阵
 /**
 * 参数 p: 明文的字符串数组。
 * 参数 plen: 明文的长度。
 * 参数 key: 密钥的字符串数组。
 */
void aes(char *p, int plen, char *key){

    int keylen = strlen(key);
    if(plen == 0 || plen % 16 != 0) {//-判断明文是否符合规范
        printf("明文字符长度必须为16的倍数!\n");
        exit(0);
    }

    if(!checkKeyLen(keylen)) {//-判断密钥是否符合规范
        printf("密钥字符长度错误!长度必须为16、24和32。当前长度为%d\n",keylen);
        exit(0);
    }

    extendKey(key);//扩展密钥
    int pArray[4][4];//-明文矩阵

    for(int k = 0; k < plen; k += 16) {
        convertToIntArray(p + k, pArray);//-明文矩阵转化为状态矩阵

        addRoundKey(pArray, 0);//0轮 轮密钥加

        for(int i = 1; i < 10; i++){//前1-9轮

            subBytes(pArray);//字节代换

            shiftRows(pArray);//行移位

            mixColumns(pArray);//列混合

            addRoundKey(pArray, i);//-轮密钥加

        }

        //第10轮
        subBytes(pArray);//字节代换

        shiftRows(pArray);//行移位

        addRoundKey(pArray, 10);//-轮密钥加

        convertArrayToStr(pArray, p + k);//-状态矩阵转化为密文矩阵
    }
}


  1. 密钥扩展
//密钥对应的扩展数组
static int w[44];//-128位AES用共用44组密钥

/**
 * 扩展密钥,结果是把w[44]中的每个元素初始化
 */
static void extendKey(char *key) {//-这个函数传入密钥key的字符串表示
    for(int i = 0; i < 4; i++)
        w[i] = getWordFromStr(key + i * 4); //-从字符串中读取W[0]到W[3]?

    for(int i = 4, j = 0; i < 44; i++) {
        if( i % 4 == 0) {//-i是4的倍数:w[i] = w[i - 4] 异或 T(w[i - 1]) ; 
            w[i] = w[i - 4] ^ T(w[i - 1], j); //-j是在计算T函数时,在轮常量异或中需要知道第几轮才能计算
            j++;//下一轮
        }else {//-i不是4的倍数:w[i] = w[i - 4] 异或 w[i - 1]
            w[i] = w[i - 4] ^ w[i - 1]; 
        }
    }   

}


/**
 * -函数T由3部分组成:字循环、字节代换和轮常量异或
 */
static const int Rcon[10] = { //-常量轮值表
    0x01000000, 0x02000000,
    0x04000000, 0x08000000,
    0x10000000, 0x20000000,
    0x40000000, 0x80000000,
    0x1b000000, 0x36000000 };
/**
 * 密钥扩展中的T函数
 */
static int T(int num, int round) {//-参数num为上面传进的W[i - 1],round为加密的轮数
    int numArray[4];//-numArray储存从32位的W[i-1]中取得4个字节
    splitIntToArray(num, numArray);//-函数splitIntToArray()用于从32位整数中读取这4个字节
    leftLoop4int(numArray, 1);//-字循环:将4个字节左循环1个字节

    //-字节代换:使用S盒字节代换
    for(int i = 0; i < 4; i++)
        numArray[i] = getNumFromSBox(numArray[i]);

    int result = mergeArrayToInt(numArray);//-通过mergeArrayToInt()函数把字节代换后的numArray合并回32位的整数
    return result ^ Rcon[round];//-将前两步的结果同轮常量Rcon[j]进行异或,其中j表示轮数,轮常量Rcon[j]是一个字
}


  1. 字节代换

/**
 * 根据索引,从S盒中获得元素
 */
static int getNumFromSBox(int index) {
    int row = getLeft4Bit(index);//-高4位作为行值
    int col = getRight4Bit(index);//-低4位作为列值
    return S[row][col];//-返回对应于S盒的某行某列
}

/**
 * 字节代换
 */
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]);
}


  1. 行移位

/**
 * 将数组中的元素循环左移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;
    }
}

/**
 * 行移位:先把状态矩阵中第2,3,4行复制出来,然后对它们行进左移相应的位数,然后再复制回去状态矩阵array中
 */
static void shiftRows(int array[4][4]) {//-输入状态矩阵
    int rowTwo[4], rowThree[4], rowFour[4];//-状态矩阵第234行
    //复制状态矩阵的第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];
    }
}


  1. 列混合
/**
 * 列混合要用到的矩阵:经行移位后的状态矩阵与固定的矩阵相乘
 */
static const int colM[4][4] = { 
    2, 3, 1, 1,
    1, 2, 3, 1,
    1, 1, 2, 3,
    3, 1, 1, 2 };
//GF2的计算
static int GFMul2(int s) {
    int result = s << 1;//-左移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++) //-复制一份状态矩阵为tempArray
        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]);
        }
}


  1. 轮密钥加

/**
 * 轮密钥加
 */
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);//-函数splitIntToArray()用于从32位整数中读取这四个字节到warry中

        for(int j = 0; j < 4; j++) {
            array[j][i] = array[j][i] ^ warray[j];//-状态矩阵与密钥异或
        }
    }
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值