AES加密算法原理及C++代码,每步均有相应代码
创始人
2025-05-31 07:09:09

本文借鉴了下文。

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

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

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

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

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

完整代码在最后

背景

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

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

#include 
#include 
#include 
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 functionaddRoundKey(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 
#include 
#include 
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; iword(矩阵)
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 functionaddRoundKey(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:字节替代变换和逆字节替代变换-----------------------"<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<

相关内容

热门资讯

张朝阳后悔“退货”!一个绝版L... 每经编辑|陈柯名 近日,“张朝阳后悔送回绝版Labubu”的词条冲上热搜。6月15日,胡润发视频透...
广州全面取消限购限价,大家为何... 好像是一个大消息,但好像又没啥人关注。多年之后广州终于全面取消限购、限价、限售,并且降低贷款首付比例...
“新消费”彻底火了!最新解读 【导读】公募投研人士研判新消费投资机会:供需双振催化增长动能,“Z世代”消费力量重塑产业格局 中国基...
A股重大调整,今日生效! 来源:证券时报 A股系列指数调样,今日(6月16日)生效! 根据此前消息,6月16日为A股系列指数定...
长城搅拌创业板IPO铩羽在即 ... 导读:虽然在深交所IPO最新公布的审核名单中,长城搅拌IPO正因“IPO申请文件中记录的财务资料已过...
不只“苏超”,这些夏日消费热度... 6月14日,游客在江苏省连云港市“在海一方”公园。中新社发 王春 摄文/冯玲玲炎炎夏日,中国消费市场...
2025年1-5月香港IPO中... 文/梧桐数据中心 2025年1-5月,共计有29家公司登陆港交所,其中27家通过IPO方式上市,另有...
原创 帮... 大家好,我是帮主郑重,做了20年财经记者,也是一直在市场中摸爬滚打的投资者。今天咱们不整虚的,直接唠...
婴儿炒股?用贝叶斯模型看美股是... 头图由豆包生成,提示词:美元 华尔街风云炒股从婴儿抓起?6月9日,特朗普在白宫主持圆桌会议,力推共和...
选股不难,对三大资金的持仓抄作... 本周资本市场热议的是泡泡玛特的股价暴涨,导致泡泡玛特的老板身价达到了1467亿元,成为了河南新首富。...
江苏知名国企换帅,去年人均薪酬... 【高管】江苏省新能源开发股份有限公司在三年内迎来第三任掌门人。5月30日,因达到法定退休年龄,朱又生...
千亿元市值巨头“A拆A”,过会 A股分拆上市审核出现新动向。 6月12日晚,记者自深交所获悉,经上市审核委员会审议,苏州汇川联合动...
百亿核爆级并购!全球TOP10... 并购重组最新消息催化 政策松绑、科技狂飙、国资凶猛,A股迎来并购大时代! 2025年5月,证监会修订...
百万拍卖、全球疯抢,Labub... 文 / 一灯来源 / 节点财经6月10日,一只的薄荷色LABUBU在永乐2025春季拍卖会中以108...
健身不成反伤身?!总台《财经调... (央视财经《财经调查》)《财经调查》栏目近期接到了多个消费者的举报,信息显示,一些生产厂家将不合格的...
财经调查丨“非标”横行!《财经... (央视财经《财经调查》)总台《财经调查》栏目近期接到了多个消费者的举报,信息显示,一些生产厂家将不合...
安井食品冲刺港股 食品行业加速... 中经记者 党鹏 成都报道继海天味业(603288.SH)之后,国内又一食品龙头企业——安井食品(60...
万亿宁王PK百亿中创新航,“战... 5年博弈,专利诉讼大战持续升级。作者 | 伍玥编辑丨高岩来源 | 野马财经道歉不到位?帮你强制执行!...
王传福亲自交车,方程豹着急走量... 记者丨覃毅 编辑丨谭璐王传福寄予厚望的方程豹,着急走量。6月中旬,这位万亿车企掌舵者空降重庆,亲自为...
广道数字连续6年半财务造假“高... 中经实习记者 孙汝祥 记者 夏欣 北京报道*ST广道(839680.BJ,广道数字)6月13日晚公告...
国际原子能机构:伊核设施多次遭... 国际原子能机构当地时间14日表示,据伊朗核监管部门通报,尽管伊朗伊斯法罕核设施在以色列空袭中受损,但...
“面板大佬”王东升又双叒要敲钟... 左手A股,右手港股,王东升的资本版图有多大?作者|刘钦文编辑|高远山在科技与资本交织的舞台上,“京东...
李嘉诚港口交易传来积极信号,中... 文丨詹詹 郭小兴编辑丨杜海来源丨新商悟(本文约为1500字)李嘉诚旗下全球港口的归属,在“悬念”了3...
投资黄金切忌短期内追涨杀跌 【投资黄金切忌短期内追涨杀跌】 在全球央行“囤金潮”的带动下,今年以来,国内黄金价格也不断创下新高,...
新模式下的上市公司易主!“国资... 启明创投收购天迈科技实控权的交易结构日前出炉,其复杂的“双GP+关联方管理人委托管理”模式,迅速成为...
150亿美元!28岁华裔天才官... 收购股份、挖角CEO,一场可能颠覆AI竞争格局的洗牌,正在硅谷上演。 日前,年仅28岁的AI数据服务...
新手买基金,ETF、LOF怎么... 点击 “简七读财” ,发送消息“理财小工具”免费领取40个赚钱工具资源包~晚上好呀~前两天,咱们聊...
有200万、300万,算中产吗... 图:锁屏美术馆闲聊一下。现在小红书等社交平台,经常有一种姨妈贴子。“我有200万、300万现金,算中...
瑞幸“上岸”,库迪“扑腾”:为... “价格屠夫”库迪还能提刀多久?作者 | 于婞编辑丨高岩来源 | 野马财经在当下的咖啡市场中,价格战的...
长钱长投!3.7万亿养老金,首... 又一类长钱顺应长期投资、长期考核趋势而出现新举措。6月13日,人力资源和社会保障部公布2025年一季...