AES加解密实现
代码如下,输入例子为《密码编码学与网络安全——原理与实践(第七版)》中的示例
明文:0123456789abcdeffedcba9876543210
密钥:0f 15 71 c9 47 d9 e8 59 0c b7 ad d6 af 7f 67 98
密文:ff0b844a0853bf7c6934ab4364148fb9
//S盒步骤:初始化,求在有限域中的逆,字节变换
//逆S盒步骤:初始化,字节变换,求在有限域中的逆
//AES加密步骤:对明文进行第0轮轮密钥加,进行9轮(字节代替、行变换、列混淆、轮密钥加),再进行字节代替、行变换、第10轮的轮密钥加
//AES揭秘步骤 :对密文进行第10轮轮密钥加以及逆向行变换、逆向字节代替,进行9轮( 轮密钥加、逆向列混淆、逆向行变换、逆向字节代替),最后进行第0轮的轮密钥加
//密钥太难输入了,直接把密钥保存在了程序里,
#include<cstdio>
int i,j;
unsigned char S[16][16],IS[16][16]; //盒子S
unsigned char w[4][44];
unsigned char ExEuclid(unsigned char b);
unsigned char RC[10] = {
0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1B,0x36};
unsigned char l[4][4]={
0x02,0x03,0x01,0x01,
0x01,0x02,0x03,0x01,
0x01,0x01,0x02,0x03,
0x03,0x01,0x01,0x02}; //列混淆变换正向矩阵
unsigned char Il[4][4]={
0x0E,0x0B,0x0D,0x09,
0x09,0x0E,0x0B,0x0D,
0x0D,0x09,0x0E,0x0B,
0x0B,0x0D,0x09,0x0E}; //列混淆变换逆向矩阵
unsigned char M[4][4];
unsigned char mc[4][4];
unsigned char Imc[4][4];
void initialize() //初始化盒子S
{
for(i=0;i<=0xF;i++)
{
for(j=0;j<=0xF;j++)
{
S[i][j]=((i << 4) + j);
//printf("%02X ",S[i][j]);
S[i][j]=ExEuclid(S[i][j]);
}
//printf("\n");
}
}
unsigned char msb(unsigned short num) //求出非0最高位
{
unsigned char i;
for(i = 0; i <= 8; i++)
{
if(!(num >> (i + 1)))
{
return i;
}
}
}
unsigned char multiply(unsigned char a, unsigned char b) //乘法实现
{
unsigned char hex=0x00;
int d[16], s[32];
int n = b, cnt = 0;
while (n)///转化为二进制
{
s[cnt++] = n % 2;
n /= 2;
}
if (cnt < 8)
{
for (;cnt < 8;cnt++)
s[cnt] = 0;
}//防止出现后面的位数为0的情况
d[0] = a;
for (int i = 0; i <= 7; i++)
{
if (d[i] & 0x80)///如果最高为为1就对不可约多项式取模,否则直接左移
d[i + 1] = ((d[i] << 1) ^ 0x1B);
else
d[i + 1] = d[i] << 1;
d[i] &= 0xFF;
if (s[i] == 1)///当二进制的这一位为1的时候才能异或
hex ^= d[i];
}
return hex;
}
unsigned char divide(unsigned short a, unsigned char b, unsigned char &r,unsigned char q) //除法实现
{
unsigned char a_msb = msb(a); //求出非0的最高位 ,a为0x11B,b为要求逆元的字段
unsigned char b_msb = msb(b);
if(a < b) //重复步骤知道被除数a小于除数b,除法运算结束
{
r = a; //此时的a为余数,记录下来便于以后的运算
return q;
}
unsigned char bit = a_msb - b_msb;
unsigned short temp = b;
temp = temp << bit;
a = a ^ temp; //将b左移也就是乘上bit后两者最高位相同,a^temp也就是a减去temp,最终能够得到a除以b的余数
q = q ^ (1 << bit); //将移位记录下来得到除法运算中的积
return divide(a, b, r,q);
}
unsigned char ExEuclid(unsigned char b) //求逆元
{
if(b == 0)
return 0;
short r0 = 0x11B;
unsigned char r1 = b, r2, q = 0x00; //r1为需要求逆元的字节
unsigned char w0 = 0, w1 = 1, w2;
q=divide(r0, r1 , r2,q);
w2 = w0 ^ multiply(q, w1); //w2=w0-q2*w1 扩展的欧几里得算法
while(1)
{
if(r2 == 0) //余数不为0,进行循环
break;
q = 0x00;
r0 = r1;