AES加密算法原理及C++代码,每步均有相应代码

本文借鉴了下文。

https://blog.csdn.net/weixin_46395886/article/details/113060749?spm=1001.2014.3001.5506

并修改和增加了如下功能:

  1. 修改列移位,上文的操作为列移位,本代码更正为行移位。

  1. 增加原文分快和补位功能:上文的明文只能是16位数,本文的代码可以输入任意位数明文。

下面详细介绍AES原理和对应代码

完整代码在最后

背景

本实验采用的编程语言为C++。将AES加解密的操作封装为名为”AES”的类。

下面首先简单介绍类”AES”,再逐个介绍其他实验内容。

#include <iostream>
#include <cstdlib>
#include <stdio.h>
using namespace std;
typedef unsigned char byte;//重命名 unsigned char
struct word
{
    byte wordKey[4];//word x,x可存储4个byte数据,索引:x.wordkey[i]
};

class AES
{
public:
    AES(int sizeplain){
        SizePlain = sizeplain;
        initRcon();//Rcon函数
    };
    // ~AES();
    void setCipherKey(byte key[]);//初始化密钥including密钥扩展
    void setPlainText(byte plain[]);//转换明文数据类型

    //密钥扩展
    void keyExpansion(byte key[], word w[]);
    word rotWord(word w);// RotByte(a,b,c,d) = (b,c,d,a)
    word subWord(word w);// S盒变换
    word wordXOR(word w1, word w2);//异或

    //加解密
    void encryption();//10轮加密算法
    void addRoundKey(word in[], int round);//加密机:密钥与输入异或
    void subByte(word in[]);//字节替代
    void shiftRows(word in[]);//行移位
    void mixColumn(word in[]);//列混淆
    byte GFMultiplyByte(byte L, byte R);
    void decryption();//10轮解密
    void invShiftRows(word in[]);//逆行移位
    void invSubByte(word in[]);//逆字节替代
    void invMixColumn(word in[]);//逆列混淆
    void initRcon();//构造函数,初始化Rcon[]
    void showWord16(word w[], int len);//输出格式:16进制数
    void showWordChar(word w[],int len);//输出格式:字符
    void showMesage(byte p[],word w[],word c[],int l3, word d[],int l4);//格式化输出
    void CoveringPlain(byte plain[]);
    void InverCover(word in[]);//去补位

    //成员变量
    int NumGroup;//明文分块后的块的数量
    int DifferValue;//补位的数值
    int SizePlain;//明文长度
    byte CoverPlain[200];//补位后的明文
    word InCoverdeCipherText[16];//解密后再去补位
    byte cipherKey[16];
    word plainText[4];//明文
    word cipherText[4];//密文
    word deCipherText[4];//解密后输出
    static const int Nb=4, Nk=4, Nr=10;
    word Rcon[11];
    word wordKey[44];//密钥
    static const byte SBox[16][16];//S盒
    static const byte invSBox[16][16];//逆S盒
    static const byte mixColumnMatrix[4][4];//列混淆常数矩阵
    static const byte invmixColumnMatrix[4][4];//逆列混淆常数矩阵
};

一.字节替代变换和逆字节替代变换

  1. 字节替代变换

  1. 字符串的补位

  1. 原理:AES属于分组加密算法,即把明文分为多段的独立明文块再依次进行加密,每个明文块的长度是128bit,对于长度不是128bit的整数倍的明文,其最后一个明文块不足128bit,这时需要对明文进行填充,使最后一个明文块凑够128bit,经过调查[1],填充数据的内容有至少三种选择,我们这里选择PKCS5Padding(默认)填充模式,其内容是如果明文块少于128bit,在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。

综上,x补位的结果应该是”abcdefghijklmn22”

  1. 代码实现:

  1. “AES”类内完成补位操作的成员函数代码


// 补位
void AES::CoveringPlain(byte plain[]){
    NumGroup = SizePlain/16 + 1;
    DifferValue = NumGroup*16 - SizePlain;
    //补位
    for (int i = 0; i < SizePlain; i++) {
        CoverPlain[i] = plain[i];
    }
    for (int i = SizePlain; i < NumGroup*16; i++) {
        CoverPlain[i] = DifferValue + '0';
    }

}
  1. 测试结果:

  1. 字符串的转码

  1. 原理:即编码:将输入字符转为数字,我们采用ASCII码进行转码。即用字符串对应的ASCII码进行编码

  1. 测试代码实现:

说明:将已经补位后的明文作为输入,输出其ASCII码对应的16进制数。事实上是把字符ASCII的16进制数作为我们的转码结果参与后面的操作。

测试结果:正确,a的ASCII码对应的16进制数是61。

  1. 字节替代

  1. 原理:字符转码后为8位16进制数,把高4位作为行值,低4位作为列值,取出S盒中对应的行列的元素作为输出,即为字节替代。

  1. 代码:

  1. “AES”类内完成字节替代操作的成员函数代码


//字节替代
void AES::subByte(word in[]){
    int i,j;
    byte L, R;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            L = in[i].wordKey[j] >> 4;
            R = in[i].wordKey[j] & 0x0f;
            in[i].wordKey[j] = SBox[L][R];
        }
    }
}
  1. 测试代码

  1. 测试结果:查表验证正确

  1. 逆字节替代变换

  1. 逆字节替代

  1. 原理:是字节替代的逆过程,过程为:把输入数据的高4位作为行值,低4位作为列值,取出逆S盒中对应的行列的元素作为输出。

  1. 代码:

  1. “AES”类内完成逆字节替代操作的成员函数代码

//逆字节替代
void AES::invSubByte(word in[]){
    int i,j;
    byte L, R;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            L = in[i].wordKey[j] >> 4;
            R = in[i].wordKey[j] & 0x0f;
            in[i].wordKey[j] = invSBox[L][R];
        }
    }
}
  1. 测试代码

  1. 逆转码

  1. 原理:ASCII码转为字符,在C++里字符就是以ASCII码的形式存储的,二者转换对于C++很容易实现。

  1. 测试代码:

这里有必要介绍两个成员函数:

void showWord16(word w[], int len);//输出w(w的数据类型为unsigned char)的ASCII码的十六进制形式。

void showWordChar(word w[],int len);//以字符的形式输出w(w的数据类型为unsigned char)。

  1. 测试结果:正确,回到了转码前补位后的结果。

  1. 去补位

  1. 原理:根据数组的最后一位和之前位的关系决定补位的数量和数值,从而去补位。

  1. 第16位和第15位不同,认为之前没有补位。

  1. 第16位和第16-j位相同,且值都为j,那么去掉数组的后j位。

  1. 代码:

  1. “AES”类内完成去补位操作的成员函数代码

//去补位
void AES::InverCover(word in[]){
    //初始化
    for (int i = 0; i < 4*NumGroup; i++)
        for (int j = 0; j < 4; j++)
            InCoverdeCipherText[i].wordKey[j] = in[i].wordKey[j];

    for (int i = 0; i < 4*NumGroup; i++) {
        for (int j = 0; j < 4; j++) {
            if(i*4+j>=SizePlain){
                InCoverdeCipherText[i].wordKey[j] = '\0';//抹去补位
            }
        }
    }
}
  1. 测试代码:正确,与明文相同。

二.行移位变换和逆行移位变换,列混合和逆列混合

  1. 行移位变换和逆行移位变换

  1. 行移位变换

  1. 原理:(1)将矩阵的第i行左移i个字节(i∈[0,3])

  1. 代码

  1. “AES”类内完成行移位变换操作的成员函数代码


//行移位
void AES::shiftRows(word in[]){
    int i,j;
    word temp[4];
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
//            temp[i].wordKey[j] = in[(i+j)%4].wordKey[j];
            temp[i].wordKey[j] = in[i].wordKey[(i+j)%4];

        }
    }
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            in[i].wordKey[j] = temp[i].wordKey[j];
        }
    }
}
  1. 测试代码

  1. 结果测试:正确

  1. 逆行移位变换

  1. 原理:将第i行(i∈[0,3])的元素循环右移i个字节

  1. 代码:

  1. “AES”类内完成逆行移位变换操作的成员函数代码

//逆行移位
void AES::invShiftRows(word in[]){
    int i,j;
    word temp[4];
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
//            temp[i].wordKey[j] = in[(i-j+4)%4].wordKey[j];
            temp[i].wordKey[j] = in[i].wordKey[(j-i+4)%4];

        }
    }
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            in[i].wordKey[j] = temp[i].wordKey[j];
        }
    }
}
  1. 测试代码

  1. 测试结果:正确

  1. 列混合和逆列混合

  1. 列混合

  1. 原理:给输入矩阵乘以一个字节矩阵,计算过程如下,其中s’是混合后矩阵,s是输入矩阵:

  1. 代码:

  1. “AES”类内完成列混淆操作的成员函数代码:列混淆由两部分组成,除了矩阵乘法外,还要定义GF(2^8)上的运算。

列混淆代码1矩阵乘法


// GF(2^8)运算
byte AES::GFMultiplyByte(byte L, byte R){
    byte temp[8];
    byte result = 0x00;
    temp[0] = L;
    int i;

    for(i=1; i<8; i++){
        if(temp[i-1] >= 0x80){
            temp[i] = (temp[i-1] << 1) ^ 0x1b;
        }else{
            temp[i] = temp[i-1] << 1;
        }
    }
    for(i=0; i<8; i++){
        if(int((R >> i) & 0x01) == 1){
            result ^= temp[i];
        }
    }
    return result;
}

测试代码

测试结果:正确,与手算结果一致

  1. 逆列混合

  1. 原理:是列混合的逆操作,计算过程如下,重要的是等式左边第一个常数矩阵的取值。

  1. 代码:

  1. “AES”类内完成逆列混淆操作的成员函数代码


//逆列混淆
void AES::invMixColumn(word in[]){
    word result[4];
    int i, j, k;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            result[i].wordKey[j] = GFMultiplyByte(invmixColumnMatrix[j][0], in[i].wordKey[0]);
            for(k=1; k<4; k++){
                result[i].wordKey[j] ^= GFMultiplyByte(invmixColumnMatrix[j][k], in[i].wordKey[k]);
            }
        }
    }
    //赋值
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            in[i].wordKey[j] = result[i].wordKey[j];
        }
    }
}


  1. 测试代码

  1. 测试结果:结果与列混淆之后,逆行移位后一样,正确。

三.轮密钥生成

  1. 原始密钥:

  1. 取值:“abcdefghijklmnop”

  1. 存储和扩展:细节如下。

  1. 代码:分以下四部分组成。

  1. 主体代码


// 密钥扩展
void AES::keyExpansion(byte key[], word w[]){
    int i=0;
    int j,k;
    word temp;
    while(i < Nk){
        for(j=0; j<4; j++){
            w[j].wordKey[i] = key[j+4*i];
        }
        i++;
    }
    i = Nk;
    while(i < Nb*(Nr+1)){
        temp = w[i-1];
        if((i%Nk) == 0){
            temp = rotWord(temp);
            temp = subWord(temp);
            temp = wordXOR(temp, Rcon[i / Nk]);
        }
        else if(Nk > 6 && (i%Nk) == 4){
            temp = subWord(temp);
        }
        w[i] = wordXOR(w[i - Nk], temp);
        i++;
    }
}
  1. RotByte函数

  1. S盒变换

  1. 异或

  1. 结果(16进制数)

  1. 测试代码

  1. 测试结果:

四.加密机和解密机

  1. 代码:

  1. 加密机:密钥与输入异或


//加密
void AES::addRoundKey(word in[], int round){
    int i, j;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            in[i].wordKey[j] ^= wordKey[i+4*round].wordKey[j];
        }
    }
}
  1. 十轮加密:加密的整体代码


//10轮加密
void AES::encryption(){
    int i, j ,k;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            cipherText[i].wordKey[j] = plainText[i].wordKey[j];
        }
    }
    // round function
    addRoundKey(cipherText, 0);
    for(i=1; i<10; i++){
        subByte(cipherText);
        shiftRows(cipherText);
        mixColumn(cipherText);
        addRoundKey(cipherText, i);
    }
    subByte(cipherText);
    shiftRows(cipherText);
    addRoundKey(cipherText, 10);
}
  1. 测试:

  1. 测试代码:其中不只有加密的完整操作也包括了完整解密的操作。

  1. 测试结果:能有密文解出密文,可见加解密操作正确。

  1. 解密机

  1. 原理:AES解密算法的初始轮和最后一轮(第10轮)的轮密钥分别是加密算法的最后一轮(第10轮)和初始轮的轮密钥,解密算法的第1轮到第9轮的轮密钥分别是加密算法的第9轮到第1轮的轮密钥经逆列混合变换后得到的。具体如下:

  1. 代码:十轮解密主体代码如下,具体的逆行移位、逆列混淆等操作前文已经介绍了,这里不再赘述。

完整代码:

#include <iostream>
#include <cstdlib>
#include <stdio.h>
using namespace std;
typedef unsigned char byte;//重命名 unsigned char
struct word
{
    byte wordKey[4];//word x,x可存储4个byte数据,索引:x.wordkey[i]
};

class AES
{
public:
    AES(int sizeplain){
        SizePlain = sizeplain;
        initRcon();//Rcon函数
    };
    // ~AES();
    void setCipherKey(byte key[]);//初始化密钥including密钥扩展
    void setPlainText(byte plain[]);//转换明文数据类型

    //密钥扩展
    void keyExpansion(byte key[], word w[]);
    word rotWord(word w);// RotByte(a,b,c,d) = (b,c,d,a)
    word subWord(word w);// S盒变换
    word wordXOR(word w1, word w2);//异或

    //加解密
    void encryption();//10轮加密算法
    void addRoundKey(word in[], int round);//加密机:密钥与输入异或
    void subByte(word in[]);//字节替代
    void shiftRows(word in[]);//行移位
    void mixColumn(word in[]);//列混淆
    byte GFMultiplyByte(byte L, byte R);
    void decryption();//10轮解密
    void invShiftRows(word in[]);//逆行移位
    void invSubByte(word in[]);//逆字节替代
    void invMixColumn(word in[]);//逆列混淆
    void initRcon();//构造函数,初始化Rcon[]
    void showWord16(word w[], int len);//输出格式:16进制数
    void showWordChar(word w[],int len);//输出格式:字符
    void showMesage(byte p[],word w[],word c[],int l3, word d[],int l4);//格式化输出
    void CoveringPlain(byte plain[]);
    void InverCover(word in[]);//去补位

    //成员变量
    int NumGroup;//明文分块后的块的数量
    int DifferValue;//补位的数值
    int SizePlain;//明文长度
    byte CoverPlain[200];//补位后的明文
    word InCoverdeCipherText[16];//解密后再去补位
    byte cipherKey[16];
    word plainText[4];//明文
    word cipherText[4];//密文
    word deCipherText[4];//解密后输出
    static const int Nb=4, Nk=4, Nr=10;
    word Rcon[11];
    word wordKey[44];//密钥
    static const byte SBox[16][16];//S盒
    static const byte invSBox[16][16];//逆S盒
    static const byte mixColumnMatrix[4][4];//列混淆常数矩阵
    static const byte invmixColumnMatrix[4][4];//逆列混淆常数矩阵
};
//去补位
void AES::InverCover(word in[]){
    //初始化
    for (int i = 0; i < 4*NumGroup; i++)
        for (int j = 0; j < 4; j++)
            InCoverdeCipherText[i].wordKey[j] = in[i].wordKey[j];

    for (int i = 0; i < 4*NumGroup; i++) {
        for (int j = 0; j < 4; j++) {
            if(i*4+j>=SizePlain){
                InCoverdeCipherText[i].wordKey[j] = '\0';//抹去补位
            }
        }
    }
}
//展示结果的16进制
void AES::showWord16(word w[], int len){
    int i,j;
    for(i=0; i<len; i++){
        for(j=0; j<4; j++){
            printf("%x ", w[i].wordKey[j]);
//            cout<<w[i].wordKey[j];
        }
    }
    cout<<endl;
}
//展示结果的字符
void AES::showWordChar(word w[],int len){
    int i,j;
    for(i=0; i<len; i++){
        for(j=0; j<4; j++){
//            printf("%x ", w[i].wordKey[j]);
            cout<<w[i].wordKey[j];
        }
    }
    cout<<endl;
}
//输出所有结果
void AES::showMesage(byte p[],word w[], word c[],int l3, word d[],int l4){
    cout<<"明文:"<<endl;
    cout<<p<<endl;
    cout<<"密钥:"<<endl;
    showWord16(w, Nb*(Nr+1));
    cout<<"密文:"<<endl;
    showWord16(c, l3);
    cout<<"解密结果:"<<endl;
    showWordChar(d, l4);
}

// 补位
void AES::CoveringPlain(byte plain[]){
    NumGroup = SizePlain/16 + 1;
    DifferValue = NumGroup*16 - SizePlain;
    //补位
    for (int i = 0; i < SizePlain; i++) {
        CoverPlain[i] = plain[i];
    }
    for (int i = SizePlain; i < NumGroup*16; i++) {
        CoverPlain[i] = DifferValue + '0';
    }

}
// 转换明文类型:byte->word(矩阵)
void AES::setPlainText(byte plain[]){
    int i;
    for(i=0; i<16; i++){
        plainText[i/4].wordKey[i%4] = plain[i];
    }
}

// 读取密钥
void AES::setCipherKey(byte key[]){
    int i;
    for(i=0; i<16; i++){
        cipherKey[i] = key[i];
    }
    keyExpansion(cipherKey, wordKey);
}

// 初始化Rcon
void AES::initRcon(){
    int i,j;
    for(i=0; i<4; i++)
        for(j=0; j<4; j++){
            Rcon[i].wordKey[j] = 0x0;
        }
    Rcon[1].wordKey[0] = 0x01;
    Rcon[2].wordKey[0] = 0x02;
    Rcon[3].wordKey[0] = 0x04;
    Rcon[4].wordKey[0] = 0x08;
    Rcon[5].wordKey[0] = 0x10;
    Rcon[6].wordKey[0] = 0x20;
    Rcon[7].wordKey[0] = 0x40;
    Rcon[8].wordKey[0] = 0x80;
    Rcon[9].wordKey[0] = 0x1b;
    Rcon[10].wordKey[0] = 0x36;
}

// 初始化列混淆常数矩阵
const byte AES::mixColumnMatrix[4][4] = {
        {0x02, 0x03, 0x01, 0x01},
        {0x01, 0x02, 0x03, 0x01},
        {0x01, 0x01, 0x02, 0x03},
        {0x03, 0x01, 0x01, 0x02}
};
// 初始化逆列混淆常数矩阵
const byte AES::invmixColumnMatrix[4][4] = {
        {0x0e, 0x0b, 0x0d, 0x09},
        {0x09, 0x0e, 0x0b, 0x0d},
        {0x0d, 0x09, 0x0e, 0x0b},
        {0x0b, 0x0d, 0x09, 0x0e}
};

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

// 密钥扩展
void AES::keyExpansion(byte key[], word w[]){
    int i=0;
    int j,k;
    word temp;
    while(i < Nk){
        for(j=0; j<4; j++){
            w[j].wordKey[i] = key[j+4*i];
        }
        i++;
    }
    i = Nk;
    while(i < Nb*(Nr+1)){
        temp = w[i-1];
        if((i%Nk) == 0){
            temp = rotWord(temp);
            temp = subWord(temp);
            temp = wordXOR(temp, Rcon[i / Nk]);
        }
        else if(Nk > 6 && (i%Nk) == 4){
            temp = subWord(temp);
        }
        w[i] = wordXOR(w[i - Nk], temp);
        i++;
    }
}

// 扩展密钥——RotByte(a,b,c,d) = (b,c,d,a)
word AES::rotWord(word w){
    int i;
    word temp;
    for(i=0; i<4; i++){
        temp.wordKey[(i+3) % 4] = w.wordKey[i];
    }
    return temp;
}
// 扩展密钥——S盒变换
word AES::subWord(word w){
    int i;
    byte L, R;
    for(i=0; i<4; i++){
        L = w.wordKey[i] >> 4;
        R = w.wordKey[i] & 0x0f;
        w.wordKey[i] = SBox[L][R];
    }
    return w;
}
// 扩展密钥——异或
word AES::wordXOR(word w1, word w2){
    int i;
    word temp;
    for(i=0; i<4; i++){
        temp.wordKey[i] = w1.wordKey[i] ^ w2.wordKey[i];
    }
    return temp;
}

//10轮加密
void AES::encryption(){
    int i, j ,k;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            cipherText[i].wordKey[j] = plainText[i].wordKey[j];
        }
    }
    // round function
    addRoundKey(cipherText, 0);
    for(i=1; i<10; i++){
        subByte(cipherText);
        shiftRows(cipherText);
        mixColumn(cipherText);
        addRoundKey(cipherText, i);
    }
    subByte(cipherText);
    shiftRows(cipherText);
    addRoundKey(cipherText, 10);
}

//字节替代
void AES::subByte(word in[]){
    int i,j;
    byte L, R;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            L = in[i].wordKey[j] >> 4;
            R = in[i].wordKey[j] & 0x0f;
            in[i].wordKey[j] = SBox[L][R];
        }
    }
}

//行移位
void AES::shiftRows(word in[]){
    int i,j;
    word temp[4];
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
//            temp[i].wordKey[j] = in[(i+j)%4].wordKey[j];
            temp[i].wordKey[j] = in[i].wordKey[(i+j)%4];

        }
    }
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            in[i].wordKey[j] = temp[i].wordKey[j];
        }
    }
}

//列混淆
void AES::mixColumn(word in[]){
    word result[4];
    int i, j, k;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            result[i].wordKey[j] = GFMultiplyByte(mixColumnMatrix[j][0], in[i].wordKey[0]);
            for(k=1; k<4; k++){
                result[i].wordKey[j] ^= GFMultiplyByte(mixColumnMatrix[j][k], in[i].wordKey[k]);
            }
        }
    }
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            in[i].wordKey[j] = result[i].wordKey[j];
        }
    }
}

// GF(2^8)运算
byte AES::GFMultiplyByte(byte L, byte R){
    byte temp[8];
    byte result = 0x00;
    temp[0] = L;
    int i;

    for(i=1; i<8; i++){
        if(temp[i-1] >= 0x80){
            temp[i] = (temp[i-1] << 1) ^ 0x1b;
        }else{
            temp[i] = temp[i-1] << 1;
        }
    }
    for(i=0; i<8; i++){
        if(int((R >> i) & 0x01) == 1){
            result ^= temp[i];
        }
    }
    return result;
}
//加密
void AES::addRoundKey(word in[], int round){
    int i, j;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            in[i].wordKey[j] ^= wordKey[i+4*round].wordKey[j];
        }
    }
}

//解密
void AES::decryption(){
    int i, j, k;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            deCipherText[i].wordKey[j] = cipherText[i].wordKey[j];
        }
    }
    addRoundKey(deCipherText, 10);
    for(i=9; i>0; i--){
        invShiftRows(deCipherText);
        invSubByte(deCipherText);
        addRoundKey(deCipherText, i);
        invMixColumn(deCipherText);
    }
    invShiftRows(deCipherText);
    invSubByte(deCipherText);
    addRoundKey(deCipherText, 0);
}
//逆行移位
void AES::invShiftRows(word in[]){
    int i,j;
    word temp[4];
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
//            temp[i].wordKey[j] = in[(i-j+4)%4].wordKey[j];
            temp[i].wordKey[j] = in[i].wordKey[(j-i+4)%4];

        }
    }
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            in[i].wordKey[j] = temp[i].wordKey[j];
        }
    }
}
//逆字节替代
void AES::invSubByte(word in[]){
    int i,j;
    byte L, R;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            L = in[i].wordKey[j] >> 4;
            R = in[i].wordKey[j] & 0x0f;
            in[i].wordKey[j] = invSBox[L][R];
        }
    }
}
//逆列混淆
void AES::invMixColumn(word in[]){
    word result[4];
    int i, j, k;
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            result[i].wordKey[j] = GFMultiplyByte(invmixColumnMatrix[j][0], in[i].wordKey[0]);
            for(k=1; k<4; k++){
                result[i].wordKey[j] ^= GFMultiplyByte(invmixColumnMatrix[j][k], in[i].wordKey[k]);
            }
        }
    }
    //赋值
    for(i=0; i<4; i++){
        for(j=0; j<4; j++){
            in[i].wordKey[j] = result[i].wordKey[j];
        }
    }
}



int main(int argc, char const *argv[])
{
    // 测试1:字节替代变换和逆字节替代变换
    cout<<"------------------test1:字节替代变换和逆字节替代变换-----------------------"<<endl;

    //1.1补位
    byte Test1Plain[]={"abcdefghijklmn"};
    int sizeplainTest1 = (sizeof (Test1Plain) - 1) / sizeof (Test1Plain[0]);//明文长度
    AES aesTest1(sizeplainTest1); //创建AES对象
    aesTest1.CoveringPlain(Test1Plain);//补位
    //结果输出
    cout<<"明文"<<endl;
    cout<<Test1Plain<<endl;
    cout<<"补位结果:"<<endl;
    cout<<aesTest1.CoverPlain<<endl;

    //1.2 转码
    cout<<"转码结果:"<<endl;
    for (int i = 0; i < 16; ++i)
        printf("%x ",aesTest1.CoverPlain[i]);//输出字符的ASCII码对应的十六进制
    cout<<endl;

    //1.3字节替代
    cout<<"字节替代结果:"<<endl;
    aesTest1.setPlainText(aesTest1.CoverPlain);//类型转换:byte->word(矩阵)
    aesTest1.subByte(aesTest1.plainText);//字节替代
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%x ",aesTest1.plainText[i].wordKey[j]);
        }
        cout<<endl;
    }

    //2.1 逆字节替代
    cout<<"逆字节替代结果:"<<endl;
    aesTest1.invSubByte(aesTest1.plainText);//字节替代
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%x ",aesTest1.plainText[i].wordKey[j]);
        }
        cout<<endl;
    }

    //2.2 逆转码
    cout<<"逆转码结果:"<<endl;
    aesTest1.showWordChar(aesTest1.plainText,4);

    //2.3 去补位
    cout<<"去补位结果:"<<endl;
    aesTest1.InverCover(aesTest1.plainText);//逆补位
    aesTest1.showWordChar(aesTest1.InCoverdeCipherText,4);//以字符展示

    //测试2:行移位变换和逆行移位变换,列混合和逆列混合
    //1.1 行移位变换
    cout<<"-------------test2:二.行移位变换和逆行移位变换,列混合和逆列混合------------------"<<endl;
    cout<<"行移位结果"<<endl;
    byte Test2Plain[]={"abcdefghijklmnop"};
    int sizeplainTest2 = (sizeof (Test2Plain) - 1) / sizeof (Test2Plain[0]);//明文长度
    AES aesTest2(sizeplainTest2); //创建AES对象
    aesTest2.setPlainText(Test2Plain);//转换为字节矩阵
    cout<<"行移位前:"<<endl;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            cout<<aesTest2.plainText[i].wordKey[j]<<" ";
        }
        cout<<endl;
    }
    aesTest2.shiftRows(aesTest2.plainText);
    cout<<"行移位结果:"<<endl;

    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            cout<<aesTest2.plainText[i].wordKey[j]<<" ";
        }
        cout<<endl;
    }
    //1。2逆行移位
    cout<<"逆行移位结果:"<<endl;
    aesTest2.invShiftRows(aesTest2.plainText);
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            cout<<aesTest2.plainText[i].wordKey[j]<<" ";
        }
        cout<<endl;
    }
    //2.1 列混淆
    aesTest2.mixColumn(aesTest2.plainText);
    cout<<"列混淆结果:"<<endl;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            printf("%x ",aesTest2.plainText[i].wordKey[j]);
        }
        cout<<endl;
    }

    //2.2 逆列混淆
    aesTest2.invMixColumn(aesTest2.plainText);
    cout<<"逆列混淆结果:"<<endl;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            cout<<aesTest2.plainText[i].wordKey[j]<<" ";
        }
        cout<<endl;
    }

    //测试3:轮密钥生成
    byte keyTest3[] = {"abcdefghijklmnop"};
    aesTest2.setCipherKey(keyTest3);//读入密钥
    cout<<"-----------------------------测试3:密钥生成--------------------------------:"<<endl;
    aesTest2.showWord16(aesTest2.wordKey,44);




    //测试4:加密机和解密机
    byte plain[] = {"CryptographyandNetworkSecurity;"};
    byte key[] = {"abcdefghijklmnop"};
    int sizeplain = (sizeof (plain) - 1) / sizeof (plain[0]);
    //加解密
    AES aes(sizeplain);//创建对象
    aes.CoveringPlain(plain);//补位
    aes.setCipherKey(key);//吸纳密钥
    word chipterText[16];//密文
    word deCipherText[4*aes.NumGroup];//解密后的密文
    //记录分块加密解密结果:
    for (int i = 0; i < aes.NumGroup; i++) {
        aes.setPlainText(aes.CoverPlain+i*16);//依次吸纳明文块
        aes.encryption();//加密
        aes.decryption();//解密
        //记录加解密结果
        for (int j = 0; j < 4; j++){
            for (int k = 0; k < 4; k++){
                chipterText[i*4+j].wordKey[k] = aes.cipherText[j].wordKey[k];
                deCipherText[i*4+j].wordKey[k] = aes.deCipherText[j].wordKey[k];
            }
        }
    }
    aes.InverCover(deCipherText);//去补位
    //输出明文、密钥、密文、解密结果
    cout<<"-------------------测试4:加密机和解密机---------------------"<<endl;
    aes.showMesage(plain,aes.wordKey,chipterText,
                   aes.NumGroup*4,aes.InCoverdeCipherText,aes.NumGroup*4);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/marujie123/article/details/129654192