AES-Rijndael加密_192bit

AES-Rijndael加密_192bit

写在前面:

高级加密标准 (AES, Advanced Encryption Standard) 为最常见的对称加密算法

由于涉及到的一些数论知识和密码学原理实在不是我等蒟蒻可以理解的,只能是不求甚解了,知实现而不知原理。

吐了!!!
在这里插入图片描述

AES密钥长度Nk(32位比特字)分组长度(32位比特字)加密轮数Nr
AES-1284410
AES-1926412
AES-2568414

0x01 S-box生成

这里写图片描述

1.1 初始化

按字节值的升序逐行初始化

for(int i=0;i<16;i++){
		for(int j=0;j<16;j++) sbox[i][j]=(i<<4)+j;
}  // 初始化

1.2 求在GF(2^8)上的逆元

使用扩展欧几里得算法

1.2.1 多项式除法
int maxhight(unsigned int val)  // 求最高位数 
{
	int i=0;
    while(val)
    {
        i++;
        val = val>>1;
    }
    return i;	
}

unsigned char division(unsigned int a,unsigned int b,unsigned int* mod)  // 多项式除法 
{
	unsigned char tmp=0x01;
	int x=maxhight(a)-maxhight(b);  // 求位数差 
	if(x<0){     // 无位差即已除尽                
		*mod=a;
		return 0;
	} 
    // 每轮求商的其中一位
	else return (tmp<<x)+division(a^(b<<x),b,mod);
    // tmp<<x 为该轮求得的商
    // division(a^(b<<x),b,mod) 为剩余部分的商
}
1.2.2 有限域GF(2^8)乘法
unsigned char add(unsigned char a,unsigned char b)  // GF(2^8)加法 
{
	return a^b;  // 实际为异或运算 
}

unsigned char xtime(unsigned char a)  // XTime运算 
{
	int flag=a>>7;           // 求最高位 
	a<<=1;                   // 左移一位 
	if(flag) a^=0x1B;        // 若最高位为 1,则与 0x1B异或 
	return a;
}

unsigned char multiplication(unsigned char a,unsigned char b)  // GF(2^8)乘法 
{
	unsigned char tmp=a;
	unsigned char res=0;
	unsigned char c=0x01;	
	for(int i=0;i<8;i++){
		if(b&c) res^=tmp;  // 取出每一位,若为 1,则加上 tmp (方法类似快速幂) 
		c<<=1;              
		tmp=xtime(tmp);    // 求 x^i 
	}
	return res;
}
1.2.3 扩展欧几里得算法
unsigned char EXTENDED_EUCLID(unsigned char b)  // 扩展欧几里得求逆元 
{
	unsigned int a=0x11B,X1=1,X2=0,X3=a,mod; 
	unsigned char Y1=0,Y2=1,Y3=b,Q,T1,T2,T3;
	if(b==0) return 0;
	while(Y3!=1)    // 辗转相除法 
	{
		Q=division(X3,Y3,&mod);
		T1=X1^multiplication(Q,Y1);
		T2=X2^multiplication(Q,Y2);
			
		X3=Y3;  // 交换被除数和除数
		Y3=mod;  // 交换除数和商
			
		X1=Y1;
		Y1=T1;
			
		X2=Y2;
		Y2=T2;
	}
	return Y2;
}

1.3 仿射变换

image-20211012235431279

for(int i=0;i<16;i++){
	for(int j=0;j<16;j++){
		unsigned char tmp[8];
    	for(int l=0;l<8;l++){
        	tmp[l]= (((sbox[i][j]>>l)&0x1)^((sbox[i][j]>>((l+4)%8))&0x1)^((sbox[i][j]>>((l+5)%8))&0x1)^((sbox[i][j]>>((l+6)%8))&0x1)^((sbox[i][j]>>((l+7)%8))&0x1)^((c>>l)&0x1)) << l;
    	}  // 取出第 l、(l+4)%8、(l+5)%8、(l+6)%8、(l+7)%8位相加再加上c的第l位 
    	sbox[i][j] = tmp[0]+tmp[1]+tmp[2]+tmp[3]+tmp[4]+tmp[5]+tmp[6]+tmp[7];
	}
}// 仿射变换 

1.4 逆 S盒

首先进行仿射变换的逆变换,再求每一字节在 GF(2^8) 上的逆元

0x02 字节代换ByteSub

把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出

image-20211013214547286

void bytesub(unsigned char sbox[16][16],unsigned char state[4][6])  // 字节代换 
{
	for(int i=0;i<4;i++){
		for(int j=0;j<6;j++){
			unsigned char h=state[i][j]>>4;  // 高 4位对应 S盒的行 
			unsigned char l=state[i][j]&0xF;  // 低 4位对应 S盒的列
			state[i][j]=sbox[h][l];
		}
	}
}

0x03 行移位ShiftRow

行移位是将状态阵列的各行进行循环移位,不同的状态行的位移量不同。

image-20211013214337996

在这里插入图片描述

void shiftrowone(unsigned char a[6])  // 行一移位 
{
	unsigned char c=a[0];
	for(int i=0;i<5;i++){
		a[i]=a[i+1];
	}
	a[5]=c;
}

void shiftrow(unsigned char state[4][6])  // 行移位 (0,1,2,3) 
{
	shiftrowone(&state[1][0]);
	shiftrowone(&state[2][0]);
	shiftrowone(&state[2][0]);
	shiftrowone(&state[3][0]);
	shiftrowone(&state[3][0]);
	shiftrowone(&state[3][0]);
}

行移位的逆变换是对状态阵列的后3列分别以位移量 Nb-C1、Nb-C2、Nb-C3 进行循环移位,使得第 i 行第 j 列的字节移位到 (j+Nb-Ci) mod Nb

0x04 列混合MixColumn

在列混合变换中,将状态阵列的每个列视为 GF(2^8) 上的多项式,再与一个固定的多项式 c(x) 进行模 x^4+1乘法。当然要求 c(x) 是模 x^4+1 可逆的多项式,否则列混合变换就是不可逆的,而使不同的输入分组对应的输出分组可能相同。

Rijndael 的设计者给出的 c(x) 为:c(x) = 03 x^3 + 01 x^2 + 01 x + 02

col

void mixcolumn(unsigned char state[4][6])  // 列混合 (03,01,01,02) 
{
	for(int i=0;i<6;i++){
		unsigned char tmp[4];
		tmp[0]=multiplication(2,state[0][i])^multiplication(3,state[1][i])^state[2][i]^state[3][i];
		tmp[1]=multiplication(2,state[1][i])^multiplication(3,state[2][i])^state[3][i]^state[0][i];
		tmp[2]=multiplication(2,state[2][i])^multiplication(3,state[3][i])^state[0][i]^state[1][i];
		tmp[3]=multiplication(2,state[3][i])^multiplication(3,state[0][i])^state[1][i]^state[2][i];
		state[0][i]=tmp[0];
		state[1][i]=tmp[1];
		state[2][i]=tmp[2];
		state[3][i]=tmp[3];
	}
}

列混合运算的逆运算是类似的,只要 d(x) 满足: (03 x^3 + 01 x^2 + 01 x + 02) * d(x) = 01

则 d(x) = 0B x^3 + 0D x^2 + 09 x + 0E

col

void invmixcolumn(unsigned char state[4][6])  // 逆列混合 (0B,0D,09,0E) 
{
	for(int i=0;i<6;i++){
		unsigned char tmp[4];
		tmp[0]=multiplication(0x0E,state[0][i])^multiplication(0x0B,state[1][i])^multiplication(0x0D,state[2][i])^multiplication(0x09,state[3][i]);
		tmp[1]=multiplication(0x0E,state[1][i])^multiplication(0x0B,state[2][i])^multiplication(0x0D,state[3][i])^multiplication(0x09,state[0][i]);
		tmp[2]=multiplication(0x0E,state[2][i])^multiplication(0x0B,state[3][i])^multiplication(0x0D,state[0][i])^multiplication(0x09,state[1][i]);
		tmp[3]=multiplication(0x0E,state[3][i])^multiplication(0x0B,state[0][i])^multiplication(0x0D,state[1][i])^multiplication(0x09,state[2][i]);
		state[0][i]=tmp[0];
		state[1][i]=tmp[1];
		state[2][i]=tmp[2];
		state[3][i]=tmp[3];
	}
}

0x05 密钥加 AddRoundKey

密钥加是将轮密钥简单的与状态阵列进行逐比特异或。

image-20211013214956892

void addroundkey(unsigned char state[4][6],unsigned char roundkey[6][4])  // 密钥加 
{
	for(int i=0;i<4;i++){
		for(int j=0;j<6;j++)
			state[i][j]^=roundkey[j][i];
	}
}

0x06 密钥编排

密钥编排是指从种子密钥得到轮密钥的过程,它由密钥扩展和轮密钥选取两部分组成,其基本原则如下:

(1) 轮密钥的比特数等于分组长度乘以轮数加1;

(2) 种子密钥被扩展成为扩展密钥;

(3) 轮密钥从扩展密钥中取,其中第1轮轮密钥取扩展密钥的前 Nb个字,第2轮轮密钥取接下来的 Nb 个字,如此下去。

image-20211013221602493
image-20211013220507078

​ 其中 Key [4*N ] 为种子密钥,看作以字节为元素的一维阵列。函数 SubByte( ) 返回:4节字,其中每一个字节都是用 Rijndael 的 S 盒作用到输入字对应的字节得到。函数 RotByte( ) 也返回4字节字,该字由输入的字循环移位得到,即当输入字为( a , b, c, e )时,输出字为( b , c , d , a )
​ 可以看出,扩展密钥的前 Nk 个字即为种子密钥,之后的每个字 W[i] 等于前一个字 W[ i -1] 与 Nk 个位置之前的字 W[ i - Nk] 的异或;不过当 i / Nk 为整数时,须先将前一字 W[ i -1] 经过以下一系列的变换:
1字节的循环移位 RotByte -> 用 S 盒进行变换 SubByte -> 异或轮常数 Rcon [ i / Nk]

扫描全能王 2021-10-13 21.53_4

image-20211013222043453

void rotbyte(unsigned char temp[4])  // 4字节循环左移一个字节 
{
	unsigned char tmp=temp[0];
	temp[0]=temp[1];
	temp[1]=temp[2];
	temp[2]=temp[3];
	temp[3]=tmp;
}

void subbyte(unsigned char temp[4],unsigned char sbox[16][16])  // 字节代换 
{
	for(int i=0;i<4;i++){
		unsigned char h=temp[i]>>4;
		unsigned char l=temp[i]<<4>>4;
		temp[i]=sbox[h][l];
	}
}

//Nk=4
void keyexpansion(unsigned char key[4*4],unsigned char w[6*13][4],unsigned char sbox[16][16])  // 密钥扩展 
{	
    unsigned char rc[10]={ 0x01000000, 0x02000000,0x04000000, 0x08000000,0x10000000, 0x20000000,0x40000000, 0x80000000,0x1b000000, 0x36000000 };
	for(int i=0;i<4;i++){
		for(int j=0;j<4;j++)
			w[i][j]=key[4*i+j];  // 继承种子密钥 
	}
	unsigned char temp[4];
	for(int i=4;i<6*13;i++){
		for(int j=0;j<4;j++)	
			temp[j]=w[i-1][j];
		if(i%4==0){
			rotbyte(temp);
			subbyte(temp,sbox);
			temp[0]^=rc[i];
		}
		for(int j=0;j<4;j++)
			w[i][j]=w[i-4][j]^temp[j];
	}
}

0x07 轮函数结构

没什么好说的

void round(unsigned char state[4][6],unsigned char w[6][4],unsigned char sbox[16][16])  // 轮函数 
{
	bytesub(sbox,state);
	shiftrow(state);
	mixcolumn(state);
	addroundkey(state,w);
}

void invround(unsigned char state[4][6],unsigned char w[6][4],unsigned char sbox[16][16])  // 逆轮函数   
{
	addroundkey(state,w);
	invmixcolumn(state);
	invshiftrow(state);
	invbytesub(sbox,state);
}

void finalround(unsigned char state[4][6],unsigned char w[6][4],unsigned char sbox[16][16])  // 最后一轮   
{
	bytesub(sbox,state);
	shiftrow(state);
	addroundkey(state,w);
}

void invfinalround(unsigned char state[4][6],unsigned char w[6][4],unsigned char invsbox[16][16])  // 逆最后一轮 
{
	addroundkey(state,w);
	invshiftrow(state);
	invbytesub(invsbox,state);
}

经过一系列我看不懂的证明,解密算法的顺序似乎可以与加密算法一样。。。

void invround(unsigned char state[4][6],unsigned char w[6][4],unsigned char sbox[16][16])  // 逆轮函数   
{
    invbytesub(sbox,state);
	invshiftrow(state);
	invmixcolumn(state);
	addroundkey(state,w);
}

void invfinalround(unsigned char state[4][6],unsigned char w[6][4],unsigned char invsbox[16][16])  // 逆最后一轮 
{
    invbytesub(invsbox,state);
	invshiftrow(state);
	addroundkey(state,w);
}

附代码:

/*
      _/_/    _/_/_/_/    _/_/_/   
   _/    _/  _/        _/          
  _/_/_/_/  _/_/_/      _/_/       
 _/    _/  _/              _/      
_/    _/  _/_/_/_/  _/_/_/              
                                        */
#include <iostream>
#include <string>
#include <cstdlib>
#include <stdio.h>
using namespace std;

unsigned char add(unsigned char a,unsigned char b)  // GF(2^8)加法 
{
	return a^b;  // 实际为异或运算 
}

unsigned char xtime(unsigned char a)  // XTime运算 
{
	int flag=a>>7;           // 求最高位 
	a<<=1;                   // 左移一位 
	if(flag) a^=0x1B;        // 若最高位为 1,则与 0x1B异或 
	return a;
}

unsigned char multiplication(unsigned char a,unsigned char b)  // GF(2^8)乘法 
{
	unsigned char tmp=a;
	unsigned char res=0;
	unsigned char c=0x01;	
	for(int i=0;i<8;i++){
		if(b&c) res^=tmp;  // 取出每一位,若为 1,则加上 tmp (方法类似快速幂) 
		c<<=1;              
		tmp=xtime(tmp);    // 求 x^i 
	}
	return res;
}

void Multiplication4Byte(unsigned char a[4],unsigned char b[4],unsigned char res[4])  //  系数在 GF(2^8)上的乘法 (4字节) 
{
	res[0]=multiplication(a[0],b[0])^multiplication(a[3],b[1])^multiplication(a[2],b[2])^multiplication(a[1],b[3]);
	res[1]=multiplication(a[1],b[0])^multiplication(a[0],b[1])^multiplication(a[3],b[2])^multiplication(a[2],b[3]);
	res[2]=multiplication(a[2],b[0])^multiplication(a[1],b[1])^multiplication(a[0],b[2])^multiplication(a[3],b[3]);
	res[3]=multiplication(a[3],b[0])^multiplication(a[2],b[1])^multiplication(a[1],b[2])^multiplication(a[0],b[3]);
}

int maxhight(unsigned int val)  // 求最高位数 
{
	int i=0;
    while(val)
    {
        i++;
        val = val>>1;
    }
    return i;	
}

unsigned char division(unsigned int a,unsigned int b,unsigned int* mod)  // 多项式除法 
{
	unsigned char tmp=0x01;
	int x=maxhight(a)-maxhight(b);  // 求位数差 
	if(x<0){                     
		*mod=a;
		return 0;
	} 
	else return (tmp<<x)+division(a^(b<<x),b,mod);  // 当前最高位加剩余部分的商 
}

unsigned char EXTENDED_EUCLID(unsigned char b)  // 扩展欧几里得求逆元 
{
	unsigned int a=0x11B,X1=1,X2=0,X3=a,mod; 
	unsigned char Y1=0,Y2=1,Y3=b,Q,T1,T2,T3;
	if(b==0) return 0;
	while(Y3!=1)    // 辗转相除法 
	{
		Q=division(X3,Y3,&mod);
		T1=X1^multiplication(Q,Y1);
		T2=X2^multiplication(Q,Y2);
			
		X3=Y3;
		Y3=mod;
			
		X1=Y1;
		Y1=T1;
			
		X2=Y2;
		Y2=T2;
	}
	return Y2;
}


void tosbox(unsigned char sbox[16][16])  // Sbox生成函数 
{
	unsigned char c=0x63;
	for(int i=0;i<16;i++){
		for(int j=0;j<16;j++) sbox[i][j]=(i<<4)+j;
	}  // 初始化 
	
	for(int i=0;i<16;i++){
		for(int j=0;j<16;j++){
			sbox[i][j]=EXTENDED_EUCLID(sbox[i][j]);
		}
	}  // 求逆元
	
	for(int i=0;i<16;i++){
		for(int j=0;j<16;j++){
			unsigned char tmp[8];
    		for(int l=0;l<8;l++){
        		tmp[l]= (((sbox[i][j]>>l)&0x1)^((sbox[i][j]>>((l+4)%8))&0x1)^((sbox[i][j]>>((l+5)%8))&0x1)^((sbox[i][j]>>((l+6)%8))&0x1)^((sbox[i][j]>>((l+7)%8))&0x1)^((c>>l)&0x1)) << l;
    		}  // 取出第 l、(l+4)%8、(l+5)%8、(l+6)%8、(l+7)%8位 并加 c的第 l位 
    		sbox[i][j] = tmp[0]+tmp[1]+tmp[2]+tmp[3]+tmp[4]+tmp[5]+tmp[6]+tmp[7];
		}
	}// 仿射变换 
}

void toinvsbox(unsigned char invsbox[16][16])  // 同上,为逆过程 
{
	unsigned char c=0x05;
	for(int i=0;i<16;i++){
		for(int j=0;j<16;j++) invsbox[i][j]=(i<<4)+j;
	}  // 初始化 
	
	for(int i=0;i<16;i++){
		for(int j=0;j<16;j++){
			unsigned char tmp[8];
    		for(int l=0;l<8;l++){
        		tmp[l]= (((invsbox[i][j]>>((l+2)%8))&0x1)^((invsbox[i][j]>>((l+5)%8))&0x1)^((invsbox[i][j]>>((l+7)%8))&0x1)^((c>>l)&0x1)) << l;
    		}
    		invsbox[i][j] = tmp[0]+tmp[1]+tmp[2]+tmp[3]+tmp[4]+tmp[5]+tmp[6]+tmp[7];
		}
	}// 仿射变换 
	for(int i=0;i<16;i++){
		for(int j=0;j<16;j++){
			invsbox[i][j]=EXTENDED_EUCLID(invsbox[i][j]);
		}
	}  // 求逆元
}

void bytesub(unsigned char sbox[16][16],unsigned char state[4][6])  // 字节代换 
{
	for(int i=0;i<4;i++){
		for(int j=0;j<6;j++){
			unsigned char h=state[i][j]>>4;  // 高 4位对应 S盒的行 
			unsigned char l=state[i][j]&0xF;  // 低 4位对应 S盒的列
			state[i][j]=sbox[h][l];
		}
	}
}

void invbytesub(unsigned char invsbox[16][16],unsigned char state[4][6])  // 逆字节代换 
{
	for(int i=0;i<4;i++){
		for(int j=0;j<6;j++){
			unsigned char h=state[i][j]>>4;
			unsigned char l=state[i][j]&0xF;
			state[i][j]=invsbox[h][l];
		}
	}
}

void shiftrowone(unsigned char a[6])  // 行一移位 
{
	unsigned char c=a[0];
	for(int i=0;i<5;i++){
		a[i]=a[i+1];
	}
	a[5]=c;
}

void invshiftrow(unsigned char state[4][6])  // 逆行移位 (6-0,6-1,6-2,6-3) 
{
	shiftrowone(&state[1][0]);
	shiftrowone(&state[1][0]);
	shiftrowone(&state[1][0]);
	shiftrowone(&state[1][0]);
	shiftrowone(&state[1][0]);
	shiftrowone(&state[2][0]);
	shiftrowone(&state[2][0]);
	shiftrowone(&state[2][0]);
	shiftrowone(&state[2][0]);
	shiftrowone(&state[3][0]);
	shiftrowone(&state[3][0]);
	shiftrowone(&state[3][0]);
}

void shiftrow(unsigned char state[4][6])  // 行移位 (0,1,2,3) 
{
	shiftrowone(&state[1][0]);
	shiftrowone(&state[2][0]);
	shiftrowone(&state[2][0]);
	shiftrowone(&state[3][0]);
	shiftrowone(&state[3][0]);
	shiftrowone(&state[3][0]);
}

void mixcolumn(unsigned char state[4][6])  // 列混合 (03,01,01,02) 
{
	for(int i=0;i<6;i++){
		unsigned char tmp[4];
		tmp[0]=multiplication(2,state[0][i])^multiplication(3,state[1][i])^state[2][i]^state[3][i];
		tmp[1]=multiplication(2,state[1][i])^multiplication(3,state[2][i])^state[3][i]^state[0][i];
		tmp[2]=multiplication(2,state[2][i])^multiplication(3,state[3][i])^state[0][i]^state[1][i];
		tmp[3]=multiplication(2,state[3][i])^multiplication(3,state[0][i])^state[1][i]^state[2][i];
		state[0][i]=tmp[0];
		state[1][i]=tmp[1];
		state[2][i]=tmp[2];
		state[3][i]=tmp[3];
	}
}

void invmixcolumn(unsigned char state[4][6])  // 逆列混合 (0B,0D,09,0E) 
{
	for(int i=0;i<6;i++){
		unsigned char tmp[4];
		tmp[0]=multiplication(0x0E,state[0][i])^multiplication(0x0B,state[1][i])^multiplication(0x0D,state[2][i])^multiplication(0x09,state[3][i]);
		tmp[1]=multiplication(0x0E,state[1][i])^multiplication(0x0B,state[2][i])^multiplication(0x0D,state[3][i])^multiplication(0x09,state[0][i]);
		tmp[2]=multiplication(0x0E,state[2][i])^multiplication(0x0B,state[3][i])^multiplication(0x0D,state[0][i])^multiplication(0x09,state[1][i]);
		tmp[3]=multiplication(0x0E,state[3][i])^multiplication(0x0B,state[0][i])^multiplication(0x0D,state[1][i])^multiplication(0x09,state[2][i]);
		state[0][i]=tmp[0];
		state[1][i]=tmp[1];
		state[2][i]=tmp[2];
		state[3][i]=tmp[3];
	}
}

void addroundkey(unsigned char state[4][6],unsigned char roundkey[6][4])  // 密钥加 
{
	for(int i=0;i<4;i++){
		for(int j=0;j<6;j++)
			state[i][j]^=roundkey[j][i];
	}
}

void rotbyte(unsigned char temp[4])  // 4字节循环左移一个字节 
{
	unsigned char tmp=temp[0];
	temp[0]=temp[1];
	temp[1]=temp[2];
	temp[2]=temp[3];
	temp[3]=tmp;
}

void subbyte(unsigned char temp[4],unsigned char sbox[16][16])  // 字节代换 
{
	for(int i=0;i<4;i++){
		unsigned char h=temp[i]>>4;
		unsigned char l=temp[i]<<4>>4;
		temp[i]=sbox[h][l];
	}
}

//Nk=4
void keyexpansion(unsigned char key[4*4],unsigned char w[6*13][4],unsigned char sbox[16][16])  // 密钥扩展 
{	
    unsigned char rc[10]={ 0x01000000, 0x02000000,0x04000000, 0x08000000,0x10000000, 0x20000000,0x40000000, 0x80000000,0x1b000000, 0x36000000 };
	for(int i=0;i<4;i++){
		for(int j=0;j<4;j++)
			w[i][j]=key[4*i+j];  // 继承种子密钥 
	}
	unsigned char temp[4];
	for(int i=4;i<6*13;i++){
		for(int j=0;j<4;j++)	
			temp[j]=w[i-1][j];
		if(i%4==0){
			rotbyte(temp);
			subbyte(temp,sbox);
			temp[0]^=rc[i];
		}
		for(int j=0;j<4;j++)
			w[i][j]=w[i-4][j]^temp[j];
	}
}

void round(unsigned char state[4][6],unsigned char w[6][4],unsigned char sbox[16][16])  // 轮函数 
{
	bytesub(sbox,state);
	shiftrow(state);
	mixcolumn(state);
	addroundkey(state,w);
}

void invround(unsigned char state[4][6],unsigned char w[6][4],unsigned char sbox[16][16])  // 逆轮函数   
{
	addroundkey(state,w);
	invmixcolumn(state);
	invshiftrow(state);
	invbytesub(sbox,state);
}

void finalround(unsigned char state[4][6],unsigned char w[6][4],unsigned char sbox[16][16])  // 最后一轮   
{
	bytesub(sbox,state);
	shiftrow(state);
	addroundkey(state,w);
}

void invfinalround(unsigned char state[4][6],unsigned char w[6][4],unsigned char invsbox[16][16])  // 逆最后一轮 
{
	addroundkey(state,w);
	invshiftrow(state);
	invbytesub(invsbox,state);
}

int main()
{
	unsigned char state[4][6];
	cout<<"请输入明文(24个字符):\n";
	for(int i=0;i<4;i++)
		for(int j=0;j<6;j++) cin>>state[i][j];
	
	// sbox生成 
	unsigned char sbox[16][16];
	tosbox(sbox);  // 生成 Sbox 
	unsigned char invsbox[16][16];
	toinvsbox(invsbox);  // 生成逆 Sbox 


	// 密钥编排
	unsigned char key[4*4],w[6*13][4];  // key存储种子密钥,w存储所有轮密钥 6*(12+1) 
	for(int i=0;i<16;i++) key[i]=rand()%256;  // 密钥随机生成 
	keyexpansion(key,w,sbox);  // 密钥扩展 
	
	// 加密Nr=12 轮 
	addroundkey(state,&w[0]);  // 密钥加 
	for(int i=0;i<11;i++)
		round(state,&w[6*(i+1)],sbox);  // 轮函数 
	finalround(state,&w[6*12],sbox);  // 最后一轮 
	cout<<"密文:\n";
	for(int i=0;i<4;i++)
		for(int j=0;j<6;j++) printf("0x%X ",state[i][j]);  // 十六进制输出 
	cout<<endl;	
	
	// 解密 
	invfinalround(state,&w[6*12],invsbox);  
	for(int i=0;i<11;i++)
		invround(state,&w[6*(11-i)],invsbox);  // 轮密钥顺序相反 
	addroundkey(state,&w[0]);
	cout<<"解密文:\n";
	for(int i=0;i<4;i++)
		for(int j=0;j<6;j++) printf("%c",state[i][j]);
	return 0;
}
// 不用谢!!!
 char 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 };

	unsigned char 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 };

参考文章:

AES128加密-S盒和逆S盒构造推导及代码实现_u011516178的博客-CSDN博客_s盒

AES加密算法的详细介绍与实现_TimeShatter的博客-CSDN博客_aes加密

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赤城封雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值