AES算法学习记录

以下以一道例题论述AES算法中字节代换,行移位,列混淆,轮密钥加一轮加密详细过程。

 

已知AES一轮迭代的输入为状态矩阵

{EA 04 65 85

 83 45 5D 96  

 5C 33 98 B0

 F0 2D AD C5},

求一轮加密输出的第一个字节。期中列混淆矩阵、轮密钥、S盒分别为:

 

1.字节代换

字节代换较为简单,对照S盒进行代换即可

代换后的矩阵为:

87  F2  4D  97
EC  6E  4C  90
4A  C3   46   E7
8C  D8  95   A6

(谢谢评论区指正,一开始看错矩阵了。。。)

2.行移位

规则如下:

第一行保持不变,第二行循环左移8bit,第三行循环左移16bit,第四行循环左移24bit

图解(图片来源于网络^):

假设矩阵为a,那么用方程表示为:a[i][j] = a[i][(i+j)%4]

于是可以得到行移位的代码:

int a[4][4] = {
    {0x87, 0xF2, 0x4D, 0x97},
    {0xEC, 0x6E, 0x4C, 0x90},
    {0x4A, 0xC3, 0x46, 0xE7},
    {0x8C, 0xD8, 0x95, 0xA6}
};
int b[4][4];//行移位后的矩阵

int main() {
    //行移位
    for(int i=0;i<=3;i++)
        for(int j=0;j<=3;j++)
            b[i][j] = a[i][(i+j)%4];
    for(int i=0;i<=3;i++) {
        for(int j=0;j<=3;j++) {
            cout<<hex<<b[i][j]<<" ";
        }
        cout<<endl;
    }
}

得到行移位后的矩阵b为:

87      f2      4d      97
6e      4c      90      ec
46      e7      4a      c3
a6      8c      d8      95

2.列混淆

 

将矩阵b右乘列混淆矩阵,这个过程称为列混淆

即:

 

计算方式:

假设b矩阵某个数为x

x * 01,为x本身

x * 02,x的二进制左移一位(右边补0),如果溢出(即如果x的二进制最高位为1),那么再异或上 1B

x * 03,结果为 (x * 02) +(这里+指异或,不是简单位相加) x,即,先乘02再异或本身,计算方法和上面一样。

举例:

02 * 87

87的二进制位 1000 0111,左移一位得到 0000 1110,因为本身的二进制最高位为1,所以再异或 1B即 

00001110 xor 00011011

得到 00010101 即:15

同理 03*6E = B2

01 * 46 = 46

01 * A6 = A6

 

于是第一行 第一列的值为 15 xor B2 xor 46 xor A6 = 47 

 

核心算法代码(下有完整代码)

int mul_mat(int x,int y) {
    if(x == 0x01) {
        return y;
    }
    else if(x == 0x02) {
        if((y&128) != 128) { //二进制首位为0
            return y<<1;
        }
        else {
            int temp = ((y<<1)&((1<<8)-1)); //向左移一位,删掉最高位(保留8位)
            return temp^(0x1b);
        }
    }
    else if(x == 0x03) {
        return mul_mat(0x02,y)^y;
    }
}

得到列混淆后的矩阵为:

47      40      a3      4c
37      d4      70      9f
94      e4      3a      42
ed      a5      a6      bc

 

4.轮密钥加

用轮密钥矩阵的第 i 列,与上面得到的列混淆矩阵的第 i 列进行异或运算,得到最后的矩阵!

 

代码:

for(int i=0;i<=3;i++) {
        for(int j=0;j<=3;j++) {
            res[j][i] = resMix[j][i] ^ round_key[j][i];
        }
    }

 

 

整体代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<bitset>
using namespace std;

int a[4][4] = {
    {0x87, 0xF2, 0x4D, 0x97},
    {0xEC, 0x6E, 0x4C, 0x90},
    {0x4A, 0xC3, 0x46, 0xE7},
    {0x8C, 0xD8, 0x95, 0xA6}
};//字节代换后的矩阵
int mixCol[4][4] = {
    {0x02, 0x03, 0x01, 0x01},
    {0x01, 0x02, 0x03, 0x01},
    {0x01, 0x01, 0x02, 0x03},
    {0x03, 0x01, 0x01, 0x02}
};//列混淆矩阵
int round_key[4][4] = {
    {0xAC, 0x19, 0x28, 0x57},
    {0x77, 0xFA, 0xD1, 0x5C},
    {0x66, 0xDC, 0x29, 0x00},
    {0xF3, 0x21, 0x41, 0x6A},
};//轮密钥矩阵

int b[4][4];//行移位后的矩阵
int resMix[4][4];//列混淆后的矩阵
int res[4][4];//轮密钥加后的矩阵

int mul_mat(int x,int y) {
    if(x == 0x01) {
        return y;
    }
    else if(x == 0x02) {
        if((y&128) != 128) { //二进制首位为0
            return y<<1;
        }
        else {
            int temp = ((y<<1)&((1<<8)-1)); //向左移一位,删掉最高位(保留8位)
            return temp^(0x1b);
        }
    }
    else if(x == 0x03) {
        return mul_mat(0x02,y)^y;
    }
}


int main() {

    cout<<"字节代换后的矩阵为:"<<endl;
    for(int i=0;i<=3;i++) {
        for(int j=0;j<=3;j++) {
            cout<<hex<<a[i][j]<<'\t';
        }
        cout<<endl;
    }

    //行移位
    for(int i=0;i<=3;i++)
        for(int j=0;j<=3;j++)
            b[i][j] = a[i][(i+j)%4];

    cout<<"行移位后的矩阵为:"<<endl;
    for(int i=0;i<=3;i++) {
        for(int j=0;j<=3;j++) {
            cout<<hex<<b[i][j]<<'\t';
        }
        cout<<endl;
    }

    //列混淆
    for(int i=0;i<=3;i++) {
        for(int j=0;j<=3;j++) {
            for(int k=0;k<=3;k++) {
                resMix[i][j] ^= mul_mat(mixCol[i][k],b[k][j]);
            }
        }
    }
    cout<<"列混淆后的矩阵为:"<<endl;
    for(int i=0;i<=3;i++) {
        for(int j=0;j<=3;j++) {
            cout<<hex<<resMix[i][j]<<'\t';
        }
        cout<<endl;
    }

    //轮密钥加
    for(int i=0;i<=3;i++) {
        for(int j=0;j<=3;j++) {
            res[j][i] = resMix[j][i] ^ round_key[j][i];
        }
    }
    cout<<"轮密钥加后的矩阵为:"<<endl;
    for(int i=0;i<=3;i++) {
        for(int j=0;j<=3;j++) {
            cout<<hex<<res[i][j]<<'\t';
        }
        cout<<endl;
    }
}

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐