$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Self-defined math definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Math symbol commands \newcommand{\intd}{\,{\rm d}} % Symbol 'd' used in integration, such as 'dx' \newcommand{\diff}{{\rm d}} % Symbol 'd' used in differentiation ... $$

AES加密算法以C++语言实现

  AES 加密算法,又被称为高级加密标准,是最为常见的分组加密算法。与国密 SM4 相同,AES 加密算法也是采用分组加密的方式。

  AES 加密算法中包含了AES-128,AES-192,AES-256 三种加密方案。每种方案中的加密分组数据块的大小均为 128bit,三种加密方案的数字后缀表示加密密钥的长度(如 AES-256 表示加密密钥的大小为 256bit)。

  AES 加密算法的处理基本单位是字节,每个 128bit 的分组都会被转换称为 16 个字节进行处理,在 AES 内部,AES 块密码的算法是在称为 state 的二维(4x4)字节数组上执行的。在用 s 表示的状态数组中,每个单独的字节有两个索引:在0 ≤ r < 4范围内的行索引 r 和在 0 ≤ c < 4 范围内的列索引 c。其中每一列又被称为一个字(word)。

AES加密流程

  加密过程中主要涉及到4个操作,分别是:字节替换,行移位,列混淆,轮密钥加。具体流程如下图(图中 in 代表 128bit 的输入,Nr 表示加密迭代的轮数,w 表示轮密钥存储矩阵),直观解释就是:
  1、将输入转换为二维矩阵的形式后,首先完成轮密钥加的操作;
  2、执行加密次数 - 1 次以下操作:{字节替换,行移位,列混淆,使用新生成密钥完成轮密钥加};
  3、执行字节替换、行移位,轮密钥加的操作。最后输出结果。

密钥扩展

  由于 AES 加密过程中需要进行迭代,需要使用到轮密钥,所以需要对初始的密钥进行扩展。初始 128bit 密钥会以字节形式以 4×4 的形式存储为二维矩阵,将每一列作为一个字。在扩展 w[i] 时,有两种情况,如果i不是4的倍数,W[i] = W[i-4] ⨁ W[i-1];如果 i 是 4 的倍数,那么 W[i] = W[i-4] ⨁ T(W[i-1]);其中 T 操作如下(ROTWORD 操作表示循环左移,SUBWORD 操作表示字替换, Rcon 表示一个固定一维矩阵)。此外,如果NK=8,此需要在加一步操作,字节替换。

 

密钥扩展实现代码

#include<iostream>
#include<bitset>
using namespace std;

const unsigned char SBox[16][16] = {
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};

const unsigned int Rcon[10] = {
    0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
    0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
};


unsigned int RotWord(unsigned int A){
    return (A >> (sizeof(unsigned int)*8 - 8) | (A << 8));
}

unsigned int SubWord(unsigned int X){
    unsigned char a3 = X & 0x00000ff;
    unsigned char a2 = (X & 0x0000ff00) >> 8;
    unsigned char a1 = (X & 0x00ff0000) >> 16;
    unsigned char a0 = (X & 0xff000000) >> 24;
    unsigned char b3 = SBox[(a3 & 0xf0) >> 4][a3 & 0x0f];
    unsigned char b2 = SBox[(a2 & 0xf0) >> 4][a2 & 0x0f];
    unsigned char b1 = SBox[(a1 & 0xf0) >> 4][a1 & 0x0f];
    unsigned char b0 = SBox[(a0 & 0xf0) >> 4][a0 & 0x0f];

    return ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3));
}

void KeyExpansion(unsigned int *key, unsigned int Nk, unsigned int Nr){
    unsigned int w[4*(Nr+1)] = {0x00000000};
    unsigned int i = 0;
    while(i <= Nk-1){
        w[i] = key[i];
        i = i + 1;
    }
    cout << "i" << " \t" << "temp" << " \t" << "w[i-Nk]" << " \t" << "w[i]" << endl;
    while(i <= 4*Nr + 3){
        unsigned int temp = w[i-1];
        if(i % Nk == 0)
            temp = SubWord(RotWord(temp))^Rcon[i/Nk-1];
        else if(Nk > 6 && i%Nk == 4)
            temp = SubWord(temp);
        w[i] = w[i-Nk]^temp;
        cout << oct << i << " \t" << hex << temp << " \t" << w[i-Nk] << " \t" << w[i] << endl;
        i = i + 1;
        
    }
}

int main(void){
    // //AES_128密钥扩展实现
    // unsigned int AES_128_Key[4] = {0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c};
    // unsigned int AES_128_Nk = 4;
    // unsigned int AES_128_Nr = 10;
    // KeyExpansion(AES_128_Key, AES_128_Nk, AES_128_Nr);
    // //AES_192密钥扩展实现
    // unsigned int AES_192_Key[6] = {0x8e73b0f7, 0xda0e6452, 0xc810f32b, 0x809079e5, 0x62f8ead2, 0x522c6b7b};
    // unsigned int AES_192_Nk = 6;
    // unsigned int AES_192_Nr = 12;
    // KeyExpansion(AES_192_Key, AES_192_Nk, AES_192_Nr);
    //AES_256密钥扩展实现
    unsigned int AES_256_Key[8] = {0x603deb10, 0x15ca71be, 0x2b73aef0, 0x857d7781, 0x1f352c07, 0x3b6108d7, 0x2d9810a3, 0x0914dff4};
    unsigned int AES_256_Nk = 8;
    unsigned int AES_256_Nr = 14;
    KeyExpansion(AES_256_Key, AES_256_Nk, AES_256_Nr);
    return 0;
}
View Code

 扩展实现结果

轮密钥加

  通过逐位异或操作将一个轮密钥与二维矩阵中的一个字组合在一起。

字节替换

  使用 S 盒的可逆非线性变换,将 state 矩阵中的每一个字节进行替换。

行移位

  行移位将 state 矩阵的每一行循环移动确定的位数。字节移位的位置数取决于行索引。

列混淆

   列混淆将 state 矩阵 的四列中的每一列乘以一个固定的矩阵。需要注意的是,此处的乘法和加法是定义在扩域GF(2^8)上。

   在给出的标准文档中,给出一个在扩域GF(2^8)上简单计算 b · 02 的方法,如下图。判断 b 的最高位是否是 0,若是,直接逻辑右移一位;否则。逻辑右移一位之后与 0x1b 按位异或。

   如果计算 b · ??,则可以将 ?? 表示成 01,02,04,08,... 异或的形式,先乘再异或。

   所以 AES 加密算法中的列混淆可以表示成下图所示。

 AES 加密算法实现

#include<iostream>
#include<bitset>
using namespace std;

//定义S盒
const unsigned char SBox[16][16] = {
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};

//定义轮常量Rcon
const unsigned int Rcon[10] = {
    0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
    0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
};

//字替代操作
unsigned int SubWord(unsigned int X){
    unsigned char a3 =  X & 0x000000ff;
    unsigned char a2 = (X & 0x0000ff00) >> 8;
    unsigned char a1 = (X & 0x00ff0000) >> 16;
    unsigned char a0 = (X & 0xff000000) >> 24;
    unsigned char b3 = SBox[(a3 & 0xf0) >> 4][a3 & 0x0f];
    unsigned char b2 = SBox[(a2 & 0xf0) >> 4][a2 & 0x0f];
    unsigned char b1 = SBox[(a1 & 0xf0) >> 4][a1 & 0x0f];
    unsigned char b0 = SBox[(a0 & 0xf0) >> 4][a0 & 0x0f];

    return ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3));
}

//定义轮密钥加操作
void ADDROUNDKEY(unsigned int *state, unsigned int *w, int num_round){
    state[0] = state[0] ^ w[4 * num_round + 0];
    state[1] = state[1] ^ w[4 * num_round + 1];
    state[2] = state[2] ^ w[4 * num_round + 2];
    state[3] = state[3] ^ w[4 * num_round + 3];
}

//定义字节代替操作
void SUBBYTES(unsigned int *state){
    state[0] = SubWord(state[0]);
    state[1] = SubWord(state[1]);
    state[2] = SubWord(state[2]);
    state[3] = SubWord(state[3]);
}

//行移位操作
unsigned int RotRows(unsigned int A, int ROW){
    return (A >> (sizeof(unsigned int)*8 - 8*ROW) | (A << 8*ROW));
}

//移位操作(8bit)
unsigned int RotWord(unsigned int A){
    return (A >> (sizeof(unsigned int)*8 - 8) | (A << 8));
}

void SHIFTROWS(unsigned int *state){
    unsigned int b0 = (state[0] & 0xff000000) | ((state[1] & 0xff000000) >> 8) | ((state[2] & 0xff000000) >> 16) | ((state[3] & 0xff000000) >> 24);
    unsigned int b1 = ((state[0] & 0x00ff0000) << 8) | (state[1] & 0x00ff0000) | ((state[2] & 0x00ff0000) >> 8 ) | ((state[3] & 0x00ff0000) >> 16);
    unsigned int b2 = ((state[0] & 0x0000ff00) << 16) | ((state[1] & 0x0000ff00) << 8) | (state[2] & 0x0000ff00) | ((state[3] & 0x0000ff00) >> 8 );
    unsigned int b3 = ((state[0] & 0x000000ff) << 24) | ((state[1] & 0x000000ff) << 16) | ((state[2] & 0x000000ff) << 8) | (state[3] & 0x000000ff);
    //cout << hex << b0 << " \t" << b1 << " \t" << b2 << " \t" << b3 << " \t" << endl;
    b0 = RotRows(b0, 0);
    b1 = RotRows(b1, 1);
    b2 = RotRows(b2, 2);
    b3 = RotRows(b3, 3);
    //cout << hex << b0 << " \t" << b1 << " \t" << b2 << " \t" << b3 << " \t" << endl;
    state[0] = (b0 & 0xff000000) | ((b1 & 0xff000000) >> 8) | ((b2 & 0xff000000) >> 16) | ((b3 & 0xff000000) >> 24);
    state[1] = ((b0 & 0x00ff0000) << 8) | (b1 & 0x00ff0000) | ((b2 & 0x00ff0000) >> 8 ) | ((b3 & 0x00ff0000) >> 16);
    state[2] = ((b0 & 0x0000ff00) << 16) | ((b1 & 0x0000ff00) << 8) | (b2 & 0x0000ff00) | ((b3 & 0x0000ff00) >> 8 );
    state[3] = ((b0 & 0x000000ff) << 24) | ((b1 & 0x000000ff) << 16) | ((b2 & 0x000000ff) << 8) | (b3 & 0x000000ff);
}

//定义扩域上的b•{02}操作
unsigned char GFMul2(unsigned char x){
    if((x & 0x80) == 0x00)
        return x << 1;
    else
        return ((x << 1) ^ 0x1b);
}

//定义扩域上的b•{03}操作
unsigned char GFMul3(unsigned char x){
    return (x^GFMul2(x));
}

//定义列混淆操作
void MIXCOLUMNS(unsigned int *state){
    for(int i = 0; i < 4; i++){
        unsigned char a0 = (state[i] & 0xff000000) >> 24;
        unsigned char a1 = (state[i] & 0x00ff0000) >> 16;
        unsigned char a2 = (state[i] & 0x0000ff00) >> 8 ;
        unsigned char a3 = (state[i] & 0xff0000ff);
        unsigned char b0 =  GFMul2(a0)^GFMul3(a1)^a2^a3;
        unsigned char b1 =  a0^GFMul2(a1)^GFMul3(a2)^a3;
        unsigned char b2 =  a0^a1^GFMul2(a2)^GFMul3(a3);
        unsigned char b3 =  GFMul3(a0)^a1^a2^GFMul2(a3);

        state[i] = (b0 << 24) | (b1 << 16) | (b2<< 8) | b3;
    }
}

//定义密钥扩展函数
void KeyExpansion(unsigned int *key, unsigned int *w, unsigned int Nk, unsigned int Nr){
    unsigned int i = 0;
    while(i <= Nk-1){
        w[i] = key[i];
        i = i + 1;
    }
    //cout << "i" << " \t" << "temp" << " \t" << "w[i-Nk]" << " \t" << "w[i]" << endl;
    while(i <= 4*Nr + 3){
        unsigned int temp = w[i-1];
        if(i % Nk == 0)
            temp = SubWord(RotWord(temp))^Rcon[i/Nk-1];
        else if(Nk > 6 && i%Nk == 4)
            temp = SubWord(temp);
        w[i] = w[i-Nk]^temp;
        //cout << oct << i << " \t" << hex << temp << " \t" << w[i-Nk] << " \t" << w[i] << endl;
        i = i + 1;
        
    }
}

int main(void){
    unsigned int input[4] = {0x3243f6a8, 0x885a308d, 0x313198a2, 0xe0370734};
    unsigned int KEY[4]   = {0x2b7e1516, 0x28aed2a6, 0xabf71588, 0x09cf4f3c};
    unsigned int Nk = 4;
    unsigned int Nr = 10;

    unsigned int w[4*(Nr+1)] = {0x00000000};
    KeyExpansion(KEY, w, Nk, Nr);//获取轮密钥
    ADDROUNDKEY(input, w, 0);
    for(int i = 1; i <= (Nr - 1); i++){
        SUBBYTES(input);
        SHIFTROWS(input);
        MIXCOLUMNS(input);
        ADDROUNDKEY(input, w, i);
    }
    SUBBYTES(input);
    SHIFTROWS(input);
    ADDROUNDKEY(input, w, Nr);
    cout << hex << input[0] << " \t" << input[1] << " \t" << input[2] << " \t" << input[3] << endl ;
    return 0;
}

测试结果

 

 参考资料

[1] FIPS 197 Advanced Encryption Standard (AES) 

posted @ 2023-06-13 15:29  素衣叹风尘  阅读(3067)  评论(0)    收藏  举报