📄 aes.cpp
字号:
//设计一个AES加密和解密算法,其中AES用到如下操作:字节转换、移动行变换、混合列变换、加循环密钥
#include<iomanip.h>
#include<iostream.h>
#include<fstream.h>
#define null 0
//变量
//************************************************************************************************************
//S_盒
const unsigned char Sbox[256] = { // forward s-box
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 char ISbox[256] = { // inverse s-box
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};
static unsigned char AesRcon[11*4]=
{
0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00,
0x1b, 0x00, 0x00, 0x00,
0x36, 0x00, 0x00, 0x00
};
//*************************************************************************************************************
//小工具函数
//*****************************************************************************
static unsigned char gfmultby01(unsigned char b)
{
return b;
}
static unsigned char gfmultby02(unsigned char b)
{
if (b < 0x80)
return (unsigned char)(int)(b <<1);
else
return (unsigned char)( (int)(b << 1) ^ (int)(0x11B) );
}
static unsigned char gfmultby03(unsigned char b)
{
return (unsigned char) ( (int)gfmultby02(b) ^ (int)b );
}
static unsigned char gfmultby09(unsigned char b)
{
return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^
(int)b );
}
static unsigned char gfmultby0b(unsigned char b)
{
return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^
(int)gfmultby02(b) ^
(int)b );
}
static unsigned char gfmultby0d(unsigned char b)
{
return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^
(int)gfmultby02(gfmultby02(b)) ^
(int)(b) );
}
static unsigned char gfmultby0e(unsigned char b)
{
return (unsigned char)( (int)gfmultby02(gfmultby02(gfmultby02(b))) ^
(int)gfmultby02(gfmultby02(b)) ^
(int)gfmultby02(b) );
}
//密钥移位函数
unsigned char* RotWord(unsigned char* word)
{
unsigned char* temp = new unsigned char[4];
temp[0] = word[1];
temp[1] = word[2];
temp[2] = word[3];
temp[3] = word[0];
return temp;
}
////////////////////////////////////////////////////////////////////////////////////////////////
//密钥字代换函数
unsigned char* SubWord(unsigned char* word)
{
unsigned char* temp = new unsigned char[4];
for(int j=0;j<4;j++)
{
temp[j] = Sbox[word[j]]; //实际上也可以写成AesSbox[[j]];因为两者相等
}
return temp;
}
//*************************************************************************
//主要函数
//***************************************************************************
void chartomatrix(unsigned char*str,unsigned char Base[][4]) //输入转换,即将输入的字符串(密钥或明文)转换成一个4*4矩阵
{
int r,c;
for(c=0;c<4;c++)
{
for(r=0;r<4;r++)
Base[r][c]=str[4 * c+r];
}
}
void ByteSub(unsigned char a[4][4],unsigned char b[4][4]) //字节转换
{
int r,c;
for(r=0;r<4;r++)
for(c=0;c<4;c++)
b[r][c]=(Sbox[a[r][c]]);
}
void IvByteSub(unsigned char a[][4],unsigned char b[][4]) //逆字节转换
{
int r,c;
for(r=0;r<4;r++)
for(c=0;c<4;c++)
b[r][c]=ISbox[a[r][c]];
}
void ShiftRow(unsigned char b[][4],unsigned char C[][4]) //行变换
{
int r,c;
for(r=0;r<4;r++)
{
for(c=0;c<4;c++)
C[r][c]=b[r][(c+r)%4];
}
}
void IvShiftRow(unsigned char b[][4],unsigned char C[][4]) //逆移动行变换
{
int r,c;
for(r=0;r<4;r++)
{
for(c=0;c<4;c++)
C[r][c]=b[r][(c+4-r)%4];
}
}
void MixColumn(unsigned char C[][4],unsigned char d[][4]) //混合列变换
{
int c;
for(c=0;c<4;c++)
d[0][c]=(unsigned char)((int)gfmultby02(C[0][c]) ^ (int)gfmultby03(C[1][c]) ^
(int)gfmultby01(C[2][c]) ^ (int)gfmultby01(C[3][c]));
for(c=0;c<4;c++)
d[1][c]=(unsigned char)((int)gfmultby01(C[0][c]) ^ (int)gfmultby02(C[1][c]) ^
(int)gfmultby03(C[2][c]) ^ (int)gfmultby01(C[3][c]));
for(c=0;c<4;c++)
d[2][c]=(unsigned char)((int)gfmultby01(C[0][c]) ^ (int)gfmultby01(C[1][c]) ^
(int)gfmultby02(C[2][c]) ^ (int)gfmultby03(C[3][c]));
for(c=0;c<4;c++)
d[3][c]=(unsigned char)((int)gfmultby03(C[0][c]) ^ (int)gfmultby01(C[1][c]) ^
(int)gfmultby01(C[2][c]) ^ (int)gfmultby02(C[3][c]));
}
void IvMixColumn(unsigned char C[][4],unsigned char d[][4]) //逆混合列变换
{
int c;
for(c=0;c<4;c++)
d[0][c]=(unsigned char)((int)gfmultby0e(C[0][c]) ^ (int)gfmultby0b(C[1][c]) ^
(int)gfmultby0d(C[2][c]) ^ (int)gfmultby09(C[3][c]));
for(c=0;c<4;c++)
d[1][c]=(unsigned char)((int)gfmultby09(C[0][c]) ^ (int)gfmultby0e(C[1][c]) ^
(int)gfmultby0b(C[2][c]) ^ (int)gfmultby0d(C[3][c]));
for(c=0;c<4;c++)
d[2][c]=(unsigned char)((int)gfmultby0d(C[0][c]) ^ (int)gfmultby09(C[1][c]) ^
(int)gfmultby0e(C[2][c]) ^ (int)gfmultby0b(C[3][c]));
for(c=0;c<4;c++)
d[3][c]=(unsigned char)((int)gfmultby0b(C[0][c]) ^ (int)gfmultby0d(C[1][c]) ^
(int)gfmultby09(C[2][c]) ^ (int)gfmultby0e(C[3][c]));
}
void AddRoundKey(unsigned char d[][4],unsigned char key[][4],unsigned char e[][4]) //加循环密钥
{
int r,c;
for(r=0;r<4;r++)
for(c=0;c<4;c++)
e[r][c]=(unsigned char)((int)d[r][c]^(int)key[r][c]);
}
void KeyProducing(unsigned char*key,unsigned char K[4][44]) //扩展初始密钥到44列
{
unsigned char BaseK[4][4]={0};
chartomatrix(key,BaseK);
int r,c;
unsigned char *temp=new unsigned char[4];
for(c=0;c<4;++c)
{
for(r=0;r<4;++r)
K[r][c]=BaseK[r][c];
}
for(c=4;c<44;c++)
{
if(c%4!=0)
for(r=0;r<4;r++)
K[r][c]=(unsigned char)((int)K[r][c-4] ^ (int)K[r][c-1]);
else
{ for(r=0;r<4;r++)
temp[r]=K[r][c-1];
//先移位,再代换,最后和轮常量异或,这个地方参考了网上的。
//因为在轮常量计算时我忽略了有限域内的模运算,下面的这种方法非常好用
temp=SubWord(RotWord(temp));
temp[0] = (unsigned char)( (int)temp[0] ^ (int) AesRcon[c+0] );
temp[1] = (unsigned char)( (int)temp[1] ^ (int) AesRcon[c+1] );
temp[2] = (unsigned char)( (int)temp[2] ^ (int) AesRcon[c+2] );
temp[3] = (unsigned char)( (int)temp[3] ^ (int) AesRcon[c+3] );
for(r=0;r<4;r++)
K[r][c]=(unsigned char)((int)K[r][c-4] ^ temp[r]);
}
}
}
void Encode(unsigned char *Mwen,unsigned char K[][44],unsigned char*out)
{
unsigned char BaseM[4][4]={0};
int round,r,c;
unsigned char Ki[4][4]={0};
unsigned char e[4][4]={0},b[4][4]={0},C[4][4]={0},d[4][4]={0};
chartomatrix(Mwen,BaseM);
for(r=0;r<4;r++)
for(c=0;c<4;c++)
Ki[r][c]=K[r][c]; //第0个循环密钥
AddRoundKey(BaseM,Ki,e); //ARK,使用第0个循环密钥
for(round=1;round<10;round++)
{
ByteSub(e,b); //字节转换
ShiftRow(b,C); //移动行变换
MixColumn(C,d); //混合列变换
for(r=0;r<4;r++)
for(c=0;c<4;c++)
Ki[r][c]=K[r][4*round+c]; //产生第round轮循环的密钥Ki
AddRoundKey(d,Ki,e); //roundth循环加密
}
ByteSub(e,b); //第10次循环加密的字节转换
ShiftRow(b,C); //第10次循环加密的移动行变换
for(r=0;r<4;r++)
for(c=0;c<4;c++)
Ki[r][c]=K[r][4*10+c]; //产生第10轮循环的密钥Ki
AddRoundKey(C,Ki,e); //10th循环加密
for(c=0;c<4;c++)
{
for(r=0;r<4;r++)
out[r+4*c]=e[r][c]; //加密结果转换成输入
}
}
void Decode(unsigned char*Miwen,unsigned char K[][44],unsigned char*out)
{
unsigned char BaseM[4][4]={0};
unsigned char Ki[4][4]={0};
unsigned char e[4][4]={0},b[4][4]={0},C[4][4]={0},d[4][4]={0};
int round,r,c;
chartomatrix(Miwen,BaseM);
for(r=0;r<4;r++)
for(c=0;c<4;c++)
Ki[r][c]=K[r][4*10+c]; //产生第10轮循环的密钥Ki
AddRoundKey(BaseM,Ki,e); //10th循环解密
for(round=9;round>0;round--)
{
IvShiftRow(e,b);
IvByteSub(b,C);
for(r=0;r<4;r++)
for(c=0;c<4;c++)
Ki[r][c]=K[r][4*round+c]; //产生第round轮循环的密钥Ki
AddRoundKey(C,Ki,d);
IvMixColumn(d,e);
}
IvShiftRow(e,b);
IvByteSub(b,C);
for(r=0;r<4;r++)
for(c=0;c<4;c++)
Ki[r][c]=K[r][c]; //产生第round轮循环的密钥Ki
AddRoundKey(C,Ki,e); //ARK,使用第0个循环密钥
for(c=0;c<4;c++)
for(r=0;r<4;r++)
out[r+4*c]=e[r][c]; //加密结果转换成输入
}
//*****************************************************************************
void main()
{
unsigned char K[4][44]={0};
unsigned char *Mwen=new unsigned char[17];
unsigned char key[]="1234567890123456";
unsigned char outjiam[16]={0};
unsigned char outjiem[16]={0};
int i;
char filename[15] ;
cout<<"这是一个AES加密/解密的程序,本程序只是为了实现AES加密算法,并不强调多功能。"<<endl
<<"所以该程序只用于加密16位的字符串,且密码长度为128 bits即16字节。但本程序的"<<endl
<<"可扩展性很强,稍加修改应该就可以加密一个文件。另外,为保密起见,程序使用内置的密码。"<<endl<<endl;
cout<<"声明:无论待加密文件有多大,本程序将只加密前16个字符形成的字符串!我把待加密字符"<<endl
<<"串写在Mwen.txt中,您可以自行建立任意文本文件,然后在下一行提示后输入其文件名。"<<endl<<endl;
cout<<"请输入待加密字符串所在文件的文件名:(文件名的长度不要超过15个字符)"<<endl;
cin>>filename;
ifstream file;
file.open(filename,ios::binary,0);
file.seekg(0,ios::beg);
file.get(Mwen,17,'#');
file.close();
cout<<"the article before being coded:"<<endl;
cout<<Mwen<<endl;
//printf("the key is:\n");
//cout<<key<<endl;
//加密前处理
KeyProducing(key,K);
Encode(Mwen,K,outjiam);
cout<<"\nthe article after being coded:\n";
for(i=0;i<16;i++)
cout<<setw(2)<<setfill('0')<<hex<<(int)outjiam[i];
cout<<endl;
//解密前处理
Decode(outjiam,K,outjiem);
cout<<"\nthe article after being decoded:\n";
for(i=0;i<16;i++)
{
if(outjiem[i] >=128)
cout<<(char)(outjiem[i]%128);
else
cout<<(char)(outjiem[i]);
}
cout<<endl<<endl;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -