本文借鉴了下文。
https://blog.csdn.net/weixin_46395886/article/details/113060749?spm=1001.2014.3001.5506
并修改和增加了如下功能:
修改列移位,上文的操作为列移位,本代码更正为行移位。
增加原文分快和补位功能:上文的明文只能是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];//逆列混淆常数矩阵
};
一.字节替代变换和逆字节替代变换
字节替代变换
字符串的补位
原理:AES属于分组加密算法,即把明文分为多段的独立明文块再依次进行加密,每个明文块的长度是128bit,对于长度不是128bit的整数倍的明文,其最后一个明文块不足128bit,这时需要对明文进行填充,使最后一个明文块凑够128bit,经过调查[1],填充数据的内容有至少三种选择,我们这里选择PKCS5Padding(默认)填充模式,其内容是如果明文块少于128bit,在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数。
综上,x补位的结果应该是”abcdefghijklmn22”
代码实现:
“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';
}
}
测试结果:
![](https://img-blog.csdnimg.cn/img_convert/019e104c41785448bbe1259780f43a71.png)
字符串的转码
原理:即编码:将输入字符转为数字,我们采用ASCII码进行转码。即用字符串对应的ASCII码进行编码
测试代码实现:
![](https://img-blog.csdnimg.cn/img_convert/ec9612db34485569e8a6f74e106ff793.png)
说明:将已经补位后的明文作为输入,输出其ASCII码对应的16进制数。事实上是把字符ASCII的16进制数作为我们的转码结果参与后面的操作。
测试结果:正确,a的ASCII码对应的16进制数是61。
![](https://img-blog.csdnimg.cn/img_convert/5e65aaa8741cab8818425e5696ecf188.png)
字节替代
原理:字符转码后为8位16进制数,把高4位作为行值,低4位作为列值,取出S盒中对应的行列的元素作为输出,即为字节替代。
代码:
“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];
}
}
}
测试代码
![](https://img-blog.csdnimg.cn/img_convert/1926e17327fb5d98bfd4c296c101cb1c.png)
测试结果:查表验证正确
![](https://img-blog.csdnimg.cn/img_convert/4300a2f46d116fa7a7b093b37ed24d44.png)
逆字节替代变换
逆字节替代
原理:是字节替代的逆过程,过程为:把输入数据的高4位作为行值,低4位作为列值,取出逆S盒中对应的行列的元素作为输出。
代码:
“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];
}
}
}
测试代码
![](https://img-blog.csdnimg.cn/img_convert/c300d749e3671e60c11f46155a43490f.png)
逆转码
原理:ASCII码转为字符,在C++里字符就是以ASCII码的形式存储的,二者转换对于C++很容易实现。
测试代码:
![](https://img-blog.csdnimg.cn/img_convert/80fc31e9ef873f5e4d42f06dcbf71c73.png)
这里有必要介绍两个成员函数:
void showWord16(word w[], int len);//输出w(w的数据类型为unsigned char)的ASCII码的十六进制形式。
void showWordChar(word w[],int len);//以字符的形式输出w(w的数据类型为unsigned char)。
![](https://img-blog.csdnimg.cn/img_convert/c3be018827ea26921a9eb1444a69c82c.png)
测试结果:正确,回到了转码前补位后的结果。
![](https://img-blog.csdnimg.cn/img_convert/53513e2003dfd782d1a9e04e4f93ec0a.png)
去补位
原理:根据数组的最后一位和之前位的关系决定补位的数量和数值,从而去补位。
第16位和第15位不同,认为之前没有补位。
第16位和第16-j位相同,且值都为j,那么去掉数组的后j位。
代码:
“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';//抹去补位
}
}
}
}
测试代码:正确,与明文相同。
![](https://img-blog.csdnimg.cn/img_convert/422752cb3a3a6ad6965387f71f8b41e2.png)
二.行移位变换和逆行移位变换,列混合和逆列混合
行移位变换和逆行移位变换
行移位变换
原理:(1)将矩阵的第i行左移i个字节(i∈[0,3])
代码
“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];
}
}
}
测试代码
![](https://img-blog.csdnimg.cn/img_convert/2575f8ee7dbef464b570de077b6c5694.png)
结果测试:正确
![](https://img-blog.csdnimg.cn/img_convert/b119b069ea86651c1f76772a6393824c.png)
逆行移位变换
原理:将第i行(i∈[0,3])的元素循环右移i个字节
代码:
“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];
}
}
}
测试代码
![](https://img-blog.csdnimg.cn/img_convert/11ef6379f5b64de31db9ab85dbe13de9.png)
测试结果:正确
![](https://img-blog.csdnimg.cn/img_convert/752000e1d07542232679c68ab0f9ea1c.png)
列混合和逆列混合
列混合
原理:给输入矩阵乘以一个字节矩阵,计算过程如下,其中s’是混合后矩阵,s是输入矩阵:
![](https://img-blog.csdnimg.cn/img_convert/3cfb125da7b9e8d561d14e2799b1494f.png)
代码:
“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;
}
测试代码
![](https://img-blog.csdnimg.cn/img_convert/ff0217b14bd76e532a32bd971007209d.png)
测试结果:正确,与手算结果一致
![](https://img-blog.csdnimg.cn/img_convert/b25a3678c9bdd9722229f191903794eb.png)
逆列混合
原理:是列混合的逆操作,计算过程如下,重要的是等式左边第一个常数矩阵的取值。
![](https://img-blog.csdnimg.cn/img_convert/70e3ddd80836d00da0cb9e8cb3008a7a.png)
代码:
“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];
}
}
}
测试代码
![](https://img-blog.csdnimg.cn/img_convert/43a88375d1ebd4d843226d7abe05ece3.png)
测试结果:结果与列混淆之后,逆行移位后一样,正确。
![](https://img-blog.csdnimg.cn/img_convert/8f63c9cb644d87bef7407fe54533fe8d.png)
三.轮密钥生成
原始密钥:
取值:“abcdefghijklmnop”
存储和扩展:细节如下。
![](https://img-blog.csdnimg.cn/img_convert/141f45c2db579a64fdcc3d89b42d28dd.png)
![](https://img-blog.csdnimg.cn/img_convert/845423b86c0db0110a044f496122e149.png)
代码:分以下四部分组成。
主体代码
// 密钥扩展
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函数
![](https://img-blog.csdnimg.cn/img_convert/deb582314cebbb091b45f5c755201c81.png)
S盒变换
![](https://img-blog.csdnimg.cn/img_convert/8272d15832220a4d84ae85c9928fa1fd.png)
异或
![](https://img-blog.csdnimg.cn/img_convert/ab3b49d02057db8ec8b032a15c66b53d.png)
结果(16进制数)
测试代码
![](https://img-blog.csdnimg.cn/img_convert/6287a9246df10bc78e3e90d1118276b7.png)
测试结果:
![](https://img-blog.csdnimg.cn/img_convert/bbc3672dd2c80024e20eac9adc104c9f.png)
四.加密机和解密机
![](https://img-blog.csdnimg.cn/img_convert/2534ccf54d583e985ee2d7883aa41a55.png)
代码:
加密机:密钥与输入异或
//加密
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];
}
}
}
十轮加密:加密的整体代码
//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);
}
测试:
测试代码:其中不只有加密的完整操作也包括了完整解密的操作。
![](https://img-blog.csdnimg.cn/img_convert/aa1c0239e646555b2859a63b3df224be.png)
测试结果:能有密文解出密文,可见加解密操作正确。
![](https://img-blog.csdnimg.cn/img_convert/36b113792d8111934a03ff46585e2302.png)
解密机
原理:AES解密算法的初始轮和最后一轮(第10轮)的轮密钥分别是加密算法的最后一轮(第10轮)和初始轮的轮密钥,解密算法的第1轮到第9轮的轮密钥分别是加密算法的第9轮到第1轮的轮密钥经逆列混合变换后得到的。具体如下:
![](https://img-blog.csdnimg.cn/img_convert/e0a5bc15a45363a43f936c592a712e57.png)
代码:十轮解密主体代码如下,具体的逆行移位、逆列混淆等操作前文已经介绍了,这里不再赘述。
![](https://img-blog.csdnimg.cn/img_convert/f4314b1a1a67eb6ea47b5cbf89c00fd1.png)
完整代码:
#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;
}