AES-Rijndael加密_192bit
写在前面:
高级加密标准 (AES, Advanced Encryption Standard) 为最常见的对称加密算法
由于涉及到的一些数论知识和密码学原理实在不是我等蒟蒻可以理解的,只能是不求甚解了,知实现而不知原理。
吐了!!!
| AES | 密钥长度Nk(32位比特字) | 分组长度(32位比特字) | 加密轮数Nr |
|---|---|---|---|
| AES-128 | 4 | 4 | 10 |
| AES-192 | 6 | 4 | 12 |
| AES-256 | 8 | 4 | 14 |
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 仿射变换

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盒中对应的行的元素作为输出

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
行移位是将状态阵列的各行进行循环移位,不同的状态行的位移量不同。


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

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

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
密钥加是将轮密钥简单的与状态阵列进行逐比特异或。

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 个字,如此下去。


其中
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]


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 };
参考文章:

1104

被折叠的 条评论
为什么被折叠?



