分组密码复习
分组密码复习
分组模式
ECB
CBC
CFB
OFB
CRT
DES
DES(Data Encryption Standard)除了初始置换和逆初始置换外,其结构与Feistel密码结构相同。
分组长度 | 密钥长度 | 轮数 |
---|---|---|
64bit | 56bit | 16 |
整体方案:
加密
将64bit的明文加密为64bit的密文,其中先对明文进行处理,主要分为以下三个阶段:
初始置换
初始置换就是重排列明文分组的64bit数据:
假设明文\(M=(x_1,...,x_{64})\),经过初始置换后得到\(X=IP(M)\)。
16轮变换
每轮都有置换和代换运算:
注意,最后一轮不进行交换,即
将64bit的输入分为左右两半各32bit,记为\(L\)和\(R\),每轮变换可以写为:$$\left{\begin{array}{l}
R_{i}=L_{i-1} \oplus f\left(R_{i-1}, K_{i}\right) \
L_{i}=R_{i-1}
\end{array}(i=\mathbf{1}, \mathbf{2}, \cdots, 16)\right.$$
其中轮密钥\(K_i\)是48bit,\(f(R,k)\)函数的计算分为扩展置换、异或、S盒变换、\(P\)置换:
- 输入右半部分32bit的\(R\),首先通过扩展置换(E表)扩展为48bit,即将\(R\)的16个比特重复一次,可以看出该置换\(E\)“扩展”了数据。
- 扩展后的48bit再与子密钥\(K_i\)异或。
- 再通过代换/选择(S盒),产生32bit的输出,其中代换是由8个S盒组成,每个S盒的输入为6bit(【行】-第1个和第6个比特;【列】-中间4比特),输出4bit。
- 最后通过一个\(P\)置换,就能产生\(f(R,k)\)的32bit的输出。
逆初始置换
在第16轮变换后的输出分为左右两半,并交换次序,再通过一个逆初始置换\(IP^{-1}\)产生64bit的密文输出。
密钥生成
加密时使用的轮密钥\(K_i\),是56bit的初始密钥通过密钥生成函数得到的,密钥生成分为:置换1、左循环移位、置换2:
置换1
56bit的初始密钥\(K\)通过置换1,分为各为28bit的左右两半,记为\(C_0\)和\(C_1\):
左循环移位
然后在第\(i\)轮对\(C_{i-1}\)和\(D_{i-1}\)进行左循环移位,移位后的结果\(C_i\)和\(D_i\)作为下一轮求子密钥的输入,也能作为置换选择2的输入。
置换2
左循环移位后的\(C_{i}\)(28bit)和\(D_{i}\)(28bit)再通过置换2就可以得到第\(i\)轮的子密钥\(K_i\)(48bit),可以看出置换2“压缩“了数据。
解密
解密与加密使用同一种算法,但子密钥使用顺序相反,即\(K_{16},...,K_1\)分别用在第一轮,....,第十六轮的变换中。
例子
手推
- 加密
- 解密
代码
(1)简单输入输出
// C语言实现
#include<stdio.h>
#include<string.h>
/*
参考链接:https://blog.csdn.net/zidane_2014/article/details/37988657
*/
int IP_Table[64] = { //IP置换矩阵
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 };
int E_Table[48] = { //扩展矩阵
32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,
8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17,
16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25,
24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 };
int P_Table[32] = { // P 盒
16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 };
int IPR_Table[64] = { //逆IP置换矩阵
40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31,
38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,
36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 };
int PC1_Table[56] = { //密钥第一次置换矩阵
57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 };
int PC2_Table[48] = { // 密钥第二次置换矩阵
14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 };
int S_Box[8][4][16] = { //8个S盒 三维数组
// S1
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
// S2
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
// S3
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
// S4
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
// S5
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
// S6
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
// S7
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
// S8
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
};
static void CharToBit(const char input[], int output[])//把CHAR转换为INT
{
int i, j;
for (j = 0; j < 8; j++)
{
for (i = 0; i < 8; i++)
{
output[7 * (j + 1) - i + j] = (input[j] >> i) & 1;
}
}
};
static void BitToChar(const int intput[], char output[])//把INT转换为CHAR
{
int i, j;
for (j = 0; j < 8; j++)
{
for (i = 0; i < 8; i++)
{
output[j] = output[j] * 2 + intput[i + 8 * j];
}
}
};
static void Xor(int* INA, int* INB, int len)//异或操作
{
int i;
for (i = 0; i < len; i++)
{
*(INA + i) = *(INA + i) ^ *(INB + i);
}
};
static void IP(const int input[64], int output[64], int table[64])//初始IP置换
{
int i;
for (i = 0; i < 64; i++)
{
output[i] = input[table[i] - 1];//减1操作不可少!!
}
};
static void E(const int input[32], int output[48], int table[48])//E扩展
{
int i;
for (i = 0; i < 48; i++)
{
output[i] = input[table[i] - 1];
}
};
static void P(const int input[32], int output[32], int table[32])//P置换
{
int i;
for (i = 0; i < 32; i++)
{
output[i] = input[table[i] - 1];
}
};
static void IP_In(const int input[64], int output[64], int table[64])//逆IP
{
int i;
for (i = 0; i < 64; i++)
{
output[i] = input[table[i] - 1];
}
};
static void PC_1(const int input[64], int output[56], int table[56])//PC_1
{
int i;
for (i = 0; i < 56; i++)
{
output[i] = input[table[i] - 1];
}
};
static void PC_2(const int input[56], int output[48], int table[48])//PC_2
{
int i;
for (i = 0; i < 48; i++)
{
output[i] = input[table[i] - 1];
}
};
static void S(const int input[48], int output[32], int table[8][4][16])//S盒压缩
{
int i = 0;
int j = 0;
int INT[8];
for (; i < 48; i = i + 6)
{
INT[j] = table[j][(input[i] << 1) + (input[i + 5])][(input[i + 1] << 3) + (input[i + 2] << 2) + (input[i + 3] << 1) + (input[i + 4])];
j++;
}
for (j = 0; j < 8; j++)
{
for (i = 0; i < 4; i++)
{
output[3 * (j + 1) - i + j] = (INT[j] >> i) & 1;
}
}
};
static void F_func(int input[32], int output[32], int subkey[48])//完成DES算法轮变换
{
int len = 48;
int temp[48] = { 0 };
int temp_1[32] = { 0 };
E(input, temp, E_Table);//E扩展变换(32bit -> 48bit)
Xor(temp, subkey, len);//与子密钥异或
S(temp, temp_1, S_Box);//压缩变换(S盒)(48bit -> 32bit)
P(temp_1, output, P_Table);//P置换
};
static void RotateL(const int input[28], int output[28], int leftCount)//完成子密钥扩展的循环左移
{
int i;
int len = 28;
for (i = 0; i < len; i++)
{
output[i] = input[(i + leftCount) % len];
}
};
static void subKey_fun(const int input[64], int Subkey[16][48])//完成16轮子密钥生成
{
int loop = 1, loop_2 = 2;
int i, j;
int c[28], d[28];
int pc_1[56] = { 0 };
int pc_2[16][56] = { 0 };
int rotatel_c[16][28] = { 0 };
int rotatel_d[16][28] = { 0 };
PC_1(input, pc_1, PC1_Table);
for (i = 0; i < 28; i++)
{
c[i] = pc_1[i];
d[i] = pc_1[i + 28];
}
int leftCount = 0;
for (i = 1; i < 17; i++)
{
if (i == 1 || i == 2 || i == 9 || i == 16)
{
leftCount += loop;
RotateL(c, rotatel_c[i - 1], leftCount);
RotateL(d, rotatel_d[i - 1], leftCount);
}
else
{
leftCount += loop_2;
RotateL(c, rotatel_c[i - 1], leftCount);
RotateL(d, rotatel_d[i - 1], leftCount);
}
}
for (i = 0; i < 16; i++)
{
for (j = 0; j < 28; j++)
{
pc_2[i][j] = rotatel_c[i][j];
pc_2[i][j + 28] = rotatel_d[i][j];
}
}
for (i = 0; i < 16; i++)
{
PC_2(pc_2[i], Subkey[i], PC2_Table);
}
};
//DES加密运算
static void DES_Efun(char input[8], char key_in[8], int output[64])
{
int Ip[64] = { 0 };//存储初始置换后的矩阵
int output_1[64] = { 0 }; //输出64bit的密文
int subkeys[16][48]; //16个子密钥(48bit的K_i)
int chartobit[64] = { 0 };
int key[64];
int l[17][32], r[17][32];
CharToBit(input, chartobit);//将输入的明文消息转换为64个二进制数
IP(chartobit, Ip, IP_Table);//IP初始置换
CharToBit(key_in, key);//将输入的初始密钥转换为二进制数
subKey_fun(key, subkeys);//密钥生成
//第0轮中的IP置换后分为左右两部分
for (int i = 0; i < 32; i++)
{
l[0][i] = Ip[i];
r[0][i] = Ip[32 + i];
}
for (int j = 1; j < 16; j++)//前15轮的操作
{
for (int k = 0; k < 32; k++)//每轮将右半部分直接赋值给下一轮左半部分
{
l[j][k] = r[j - 1][k];
}
F_func(r[j - 1], r[j], subkeys[j - 1]);//使用初始密钥(正序)
Xor(r[j], l[j - 1], 32);//将f函数与左半部分异或得到下一轮右半部分
}
int t = 0;
for (t = 0; t < 32; t++)//最后一轮的操作
{
r[16][t] = r[15][t]; //将第15轮的右半部分直接赋值给第16轮的右半部分
}
F_func(r[15], l[16], subkeys[15]);//使用第16个子密钥
Xor(l[16], l[15], 32);//将f函数与左半部分异或得到下一轮左半部分
for (t = 0; t < 32; t++)//合并左右半部分
{
output_1[t] = l[16][t];
output_1[32 + t] = r[16][t];
}
//IP逆置换
IP_In(output_1, output, IPR_Table);
};
//完成DES解密运算
static void DES_Dfun(int input[64], char key_in[8], char output[8])
{
int Ip[64] = { 0 };//存储初始置换后的矩阵
int output_1[64] = { 0 };
int output_2[64] = { 0 };
int subkeys[16][48];
int chartobit[64] = { 0 };
int key[64];
int l[17][32], r[17][32];
IP(input, Ip, IP_Table);//正确,IP初始置换!
CharToBit(key_in, key);//正确!
subKey_fun(key, subkeys);//正确!
for (int i = 0; i < 32; i++)
{
l[0][i] = Ip[i];
r[0][i] = Ip[32 + i];
}
for (int j = 1; j < 16; j++)//前15轮的操作
{
for (int k = 0; k < 32; k++)
{
l[j][k] = r[j - 1][k];
}
F_func(r[j - 1], r[j], subkeys[16 - j]);//使用初始密钥(倒序)
Xor(r[j], l[j - 1], 32);
}
int t = 0;
for (t = 0; t < 32; t++)//最后一轮的操作
{
r[16][t] = r[15][t];
}
F_func(r[15], l[16], subkeys[0]);
Xor(l[16], l[15], 32);
for (t = 0; t < 32; t++)
{
output_1[t] = l[16][t];
output_1[32 + t] = r[16][t];
}
IP_In(output_1, output_2, IPR_Table);
BitToChar(output_2, output);
};
int main()
{
int output[64] = { 0 };
char MIN[9] = { 0 }; // 明文
char MI[9] = { 0 }; //秘钥
printf("请输入明文(8个字符):");
gets(MIN);
printf("请输入秘钥(8个字符):");
gets(MI);
DES_Efun(MIN, MI, output);
printf("密文如下:\n");
for (int i = 0; i < 64; i++)
{
printf("%d", output[i]);
if ((i + 1) % 4 == 0)
printf("\n");
}
printf("\n");
printf("解密功能\n");
DES_Dfun(output, MI, MIN);
printf("明文如下:\n");
for (int i = 0; i < 8; i++)
{
printf("%c", MIN[i]);
}
printf("\n");
return 0;
}
(2)openSSL库
调用函数,实现一个分组的加解密(DES-ECB模式)
#include <iostream>
#include "openssl/des.h"
using namespace std;
/*
* DES-ECB模式加解密测试
*/
int main() {
//明文
unsigned char data[]="1234567";
//密钥
unsigned char key[]="abcdefg";
//密文
unsigned char cip[]={0};
//输出
unsigned char out[]={0};
DES_key_schedule key_sch; //实际存储密钥
//密钥生成
DES_set_key((const_DES_cblock*)&key,&key_sch);
//加密
DES_ecb_encrypt((const_DES_cblock*)&data,(DES_cblock*)&cip,&key_sch,DES_ENCRYPT);
cout << "密文:"<<cip<<endl;
//解密
DES_ecb_encrypt((const_DES_cblock*)&cip,(DES_cblock*)&out,&key_sch,DES_DECRYPT);
cout << "明文:" <<out<<endl;
return 0;
}
AES
Advanced Encryption Standard,起初是Square算法,然后是Rijndael算法,第三轮确定为AES。
算法 | 密钥长度 | 分组长度 | 轮数 |
---|---|---|---|
AES-128 | 128bit | 128bit | 10 |
AES-192 | 192bit | 128bit | 12 |
AES-256 | 256bit | 128bit | 14 |
AES的处理单位是字节,一般明文分组用字节为单位的矩阵表示,称为“状态矩阵(Status)”(从上到下,从左到右)四行(32bit),\(N_b\)列【分组长度/32】,每一轮变变化,状态矩阵的内容不断发生变化,输入矩阵和输出矩阵如下:
如上面所示,每列称为一个32bit的“字”,所以在AES中:32bit = 4个字节 =1个”字“
另外初始密钥也是类似用一个矩阵表示,四行(32bit),\(N_k\)列【分组长度/32】。
迭代轮数\(N_r\)与\(N_k\)和\(N_b\)相关,具体如下:
下面以AES-128为例介绍:
加密
- 轮函数
加密主要分为10轮,前9轮都是一样的,分为:字节代换、行移位、列混合和轮密钥加,最后一轮执行列混合,另外在第一轮开始前,先将明文与初始密钥进行一次轮密钥加。
轮函数的代码为:
AddRoundKey(State, RoundKey); //轮密钥加
//前9轮
Round(State, RoundKey){
ByteSub(State); //字节代换
ShiftRow(State); //行移位
MixColumn(State); //列混合
AddRoundKey(State, RoundKey); //轮密钥加
}
//第10轮
FinalRound(State, RoundKey){
ByteSub(State); //字节代换
ShiftRow(State); //行移位
AddRoundKey(State, RoundKey); //轮密钥加
}
字节代换
字节代换是对单个字节做非线性的变换,操作是可逆的,记为\(ByteSub(Status)\),由两个可逆变换组成,有两种计算方法:
(1)两种变换
- 首先,将字节看作是\(GF(2^8)\)上的元素,即转换成一个多项式,然后计算出该多项式的乘法逆元,其中\(00\)的乘法逆元是自己。
- 然后对字节做仿射变换:
(2)查(S盒)表
一个字节的高四位为行,低四位为列
下面是一个字节代换的例子:
行移位
行移位(ShiftRow)就是将状态矩阵各行进行循环移位,不同行的移位量是不同的。移位量\(C_1,C_2,C_3\)的取值是与\(N_b\)有关。
例如:
列混合
列混合(MixColumn)是将状态矩阵的每列看作是一个\(GF(2^8)\)上的多项式,再与一个固定的多项式\(c(x)=03x^3+01x^2+01x+02\)模\(x^4+1\)乘,所以列混合也可以看作是矩阵乘法,即\(b(x)=c(x)\otimes a(x)\):
例如:
轮密钥加
密钥加(AddRoundKey)就是将轮密钥与状态矩阵逐比特异或,即128bit的状态和128bit的密钥逐位异或,其中轮密钥就是由初始密钥通过密钥编排算法得到。
加密算法
Enc(State, CipherKey)
KeyExpansion (CipherKey, ExpandedKey);//密钥编排算法
AddRoundKey (State, ExpandedKey);//轮密钥加
For (i=l; i<10; i++) Round (State, ExpandedKey + 4 * i);//轮函数
FinalRound (State, ExpandedKey + 4 * 10)//轮密钥加
}
密钥编排
密钥编排就是从初始密钥得到轮密钥的过程,分为密钥扩展和轮密钥选取两部分。
密钥扩展
密钥扩展就是从一个初始密钥中生成多重密钥以代替使用耽搁密钥,大大增加了比特位的扩散。
输入4字,输出44字,即输入128bit,输出11*128bit
- 输入128bit(4个字)的初始密钥,将其转换为一个\(4*4\)的矩阵,每列为一个矩阵,依次为\(w[0],w[1],w[2],w[3]\)。
- 密钥扩展就是从\(w[0],w[1],w[2],w[3]\)中扩展出\(w[0],...,w[43]\),主要分为两种情况:
- 对于下标不是4的倍数的,即对于\(w[i]\),其中\(i\%4 \ne 0\)时
- \(w[i]=w[i-1]\oplus w[i-4]\),例如\(w[5]=w[4]\oplus w[1]\)
- 对于下标是4的倍数的,即对于\(w[i]\),其中\(i\%4 = 0\)时
- \(w[i]=w[i-4]\oplus T(w[i-4])\),其中\(T(w[i-1])\)是一个函数,由三部分组成:字循环、字节代换和轮常量异或
- 字循环:将一个“字”(4字节)左循环移1位,即\([b_0,b_1,b_2,b_3] \to[b_1,b_2,b_3,b_0]\)
- 字节代换:将一个“字”(4字节)输入到S盒中代换,得到新的一个“字”(4字节)
- 轮常量异或:将字节代换后的一个“字”(4字节)和轮常量\(Rcon[i]\)异或,其中每轮的轮常量\(Rcon[i]\)均不同,这是为了防止不同轮中产生的轮密钥的对称性和相似性。
- \(w[i]=w[i-4]\oplus T(w[i-4])\),其中\(T(w[i-1])\)是一个函数,由三部分组成:字循环、字节代换和轮常量异或
- 对于下标不是4的倍数的,即对于\(w[i]\),其中\(i\%4 \ne 0\)时
轮密钥选取
由密钥扩展得到44个“字”,即\(w[0],...,w[43]\),现对10个轮密钥进行选取:
1轮: \(w[4],...,w[7]\)
....
10轮: \(w[40],...,w[43]\)
满足:第\(i\)轮的轮密钥为\(w[4*1]~w[4(i+1)-1]\)。
解密
解密与加密结构相同,只是将各计算部件换为对应的逆部件,例如:
-
逆字节变换:InvByteSub
-
逆行移位:InvShiftRow
-
逆列混合:InvMixColumn
-
逆轮密码加:AddRoundKey(InvKey)
轮函数算法:
AddRoundKey(State, RoundKey); //轮密钥加
//前9轮
InvRound(State, RoundKey){
InvByteSub(State); //字节代换
InvShiftRow(State); //行移位
InvMixColumn(State); //列混合
AddRoundKey(State, RoundKey); //轮密钥加
}
//第10轮
InvFinalRound(State, RoundKey){
InvByteSub(State); //字节代换
InvShiftRow(State); //行移位
AddRoundKey(State, RoundKey); //轮密钥加
}
设加密算法的轮密钥为:\(k(0),k(1),...,k(9),k(10)\)
则解密算法的轮密钥为:\(k(10),InvMixColumn(k(9)),...InvMixColumn(k(1)),k(0)\)
例子
(1)实现加解密测试(128,192,256)和分组模式测试(ECB、CBC、OFB)
#include <iostream>
#include <iomanip>
#include "AES.h"
using namespace std;
void enc_Test()
{
int choose=0;
cout<<endl<<"加解密测试-选择:"
"1:AES-128bit-10轮;"
"2:AES-192bit-12轮"
"3:AES-256bit-14轮"<<endl;
cin>>choose;
const unsigned int BLOCK_BYTES_LENGTH = 16 * sizeof(unsigned char);
if(choose==1)
{
cout<<"-----------------------------AES-128bit-10轮-----------------------------"<<endl;
AES aes(AESKeyLength::AES_128);
cout<<"明文:";
unsigned char plain[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)plain[i]<<" ";
cout<<endl<<"密钥:";
unsigned char key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)key[i]<<" ";
cout<<endl<<"加密后:";
unsigned char *cip = aes.EncryptECB(plain, BLOCK_BYTES_LENGTH, key);
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)cip[i]<<" ";
cout<<endl<<"解密后:";
unsigned char *out = aes.DecryptECB(cip,BLOCK_BYTES_LENGTH, key);
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)out[i]<<" ";
} else if(choose==2)
{
cout<<"-----------------------------AES-192bit-12轮-----------------------------"<<endl;
const unsigned int BLOCK_BYTES_LENGTH = 16 * sizeof(unsigned char);
AES aes(AESKeyLength::AES_192);
cout<<"明文:";
unsigned char plain[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)plain[i]<<" ";
cout<<endl<<"密钥:";
unsigned char key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
for(int i=0;i<24;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)key[i]<<" ";
cout<<endl<<"加密后:";
unsigned char *cip = aes.EncryptECB(plain, BLOCK_BYTES_LENGTH, key);
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)cip[i]<<" ";
cout<<endl<<"解密后:";
unsigned char *out = aes.DecryptECB(cip,BLOCK_BYTES_LENGTH, key);
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)out[i]<<" ";
}else if(choose==3)
{
cout<<"-----------------------------AES-256bit-14轮-----------------------------"<<endl;
const unsigned int BLOCK_BYTES_LENGTH = 16 * sizeof(unsigned char);
AES aes(AESKeyLength::AES_256);
cout<<"明文:";
unsigned char plain[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)plain[i]<<" ";
cout<<endl<<"密钥:";
unsigned char key[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f};
for(int i=0;i<32;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)key[i]<<" ";
cout<<endl<<"加密后:";
unsigned char *cip = aes.EncryptECB(plain, BLOCK_BYTES_LENGTH, key);
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)cip[i]<<" ";
cout<<endl<<"解密后:";
unsigned char *out = aes.DecryptECB(cip,BLOCK_BYTES_LENGTH, key);
for(int i=0;i<16;i++)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)out[i]<<" ";
}else
cout<<"输入错误!"<<endl;
}
//模式测试
void modles_Test()
{
int choose=0;
cout<<endl<<"分组模式测试-选择:"
"1:AES-ECB-128bit;"
"2:AES-CBC-128bit"
"3:AES-CFB-128bit"<<endl;
cin>>choose;
const unsigned int BLOCK_BYTES_LENGTH = 16 * sizeof(unsigned char);
if(choose==1)
{
cout<<"-----------------------------AES-ECB-128bit-----------------------------"<<endl;
AES aes(AESKeyLength::AES_128);
cout<<"明文:";
vector<unsigned char> plain = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb,
0xcc, 0xdd, 0xee, 0xff};
for(auto i:plain)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
cout<<endl<<"密钥:";
vector<unsigned char> key = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
for(auto i:key)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
cout<<endl<<"加密后:";
vector<unsigned char> cip = aes.EncryptECB(plain, key);
for(auto i:cip)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
cout<<endl<<"解密后:";
vector<unsigned char> out = aes.DecryptECB(cip, key);
for(auto i:out)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
} else if(choose==2)
{
cout<<"-----------------------------AES-CBC-128bit-----------------------------"<<endl;
AES aes(AESKeyLength::AES_128);
cout<<"明文:";
vector<unsigned char> plain = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb,
0xcc, 0xdd, 0xee, 0xff};
for(auto i:plain)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
vector<unsigned char> iv = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff}; //初始化向量
cout<<endl<<"密钥:";
vector<unsigned char> key = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
for(auto i:key)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
cout<<endl<<"加密后:";
vector<unsigned char> cip = aes.EncryptCBC(plain, key, iv);
for(auto i:cip)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
cout<<endl<<"解密后:";
vector<unsigned char> out = aes.DecryptCBC(cip, key, iv);
for(auto i:out)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
}else if(choose==3)
{
cout<<"-----------------------------AES-CFB-128bit-----------------------------"<<endl;
AES aes(AESKeyLength::AES_128);
cout<<"明文:";
vector<unsigned char> plain = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb,
0xcc, 0xdd, 0xee, 0xff};
for(auto i:plain)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
vector<unsigned char> iv = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff}; //初始化向量
cout<<endl<<"密钥:";
vector<unsigned char> key = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
for(auto i:key)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
cout<<endl<<"加密后:";
vector<unsigned char> cip = aes.EncryptCFB(plain, key, iv);
for(auto i:cip)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
cout<<endl<<"解密后:";
vector<unsigned char> out = aes.DecryptCFB(cip, key, iv);
for(auto i:out)
cout<<setfill('0')<<setw(2)<<hex<<(unsigned int)i<<" ";
}else
cout<<"输入错误!"<<endl;
}
int main() {
enc_Test();
cout<<endl;
modles_Test();
return 0;
}