密码学 实验报告
实验 2. DES 密码算法的设计与实现
1. 实验目的
通过用 DES 算法对实际的数据进行加密和解密,深刻理解 DES 算法的设
计机制、分组密码算法工作模式。
2.实验任务
(1)分别用 DES 的几种工作模式和 3DES 完成对一个文件的加/解密,并提
交程序代码和执行结果;
(2)使用(1)中实现的程序,对输入的文本进行加密,比较输入和输出。
当把输入的文本做微小改变时(如把字符 a 替换为 b),比较输出的变化,并说
明原因。
2. 实验环境
信息楼西 505,WindowsXP,VC++6.0 平台
3. 程序设计及核心代码(可以画流程图进行辅助说明)
程序的具体功能大体分为四大模块,类型转换功能,完成字符和二进制之间的相互转换;加密功能,完成
DES 加密;密钥扩展,完成 DES 密钥扩展功能;解密功能,完成 DES 解密。
(1) 变量定义说明:
//IP 置换矩阵
int IP_Table[64] = {
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] = {
4,
5,
4, 5,
2, 3,
1,
32,
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
6,
7, 8,
9,
};
// P 盒
int P_Table[32] = {
16, 7, 20, 21, 29, 12, 28, 17, 1,
2,
8, 24, 14, 32, 27, 3,
15, 23, 26, 5,
18, 31, 10,
9, 19, 13, 30, 6, 22, 11, 4,
25};
//逆 IP 置换矩阵
int IPR_Table[64] = {
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] = {
2, 59, 51, 43, 35, 27, 19, 11,
57, 49, 41, 33, 25, 17,
10,
63, 55, 47, 39, 31, 23, 15,
14,
9, 1, 58, 50, 42, 34, 26, 18,
3, 60, 52, 44, 36,
7, 62, 54, 46, 38, 30, 22,
4
5, 28, 20, 12,
6, 61, 53, 45, 37, 29, 21, 13,
// 密钥第二次置换矩阵
int PC2_Table[48] = {
3, 28, 15,
5,
8, 16,
1,
4, 26,
14, 17, 11, 24,
23, 19, 12,
41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
7, 27, 20, 13,
6, 21, 10,
2,
//8 个 S 盒 三维数组
int S_Box[8][4][16] = {
};
};
3, 10,
1,
4, 14,
8, 13,
8,
1, 10,
2, 15, 11,
2, 13,
6, 2, 11, 15, 12,
8, 2,
4,
9, 1,
7,
6, 12,
5, 9,
0,
7,
6, 12, 11,
7,
3, 14, 10,
9,
5, 11,
5,
9,
3, 10,
8, 14,
6, 11,
3,
4, 9,
7,
2, 13, 12,
4,
7, 15,
7, 11, 10,
2, 8, 14, 12,
4, 13,
1, 5,
0, 1, 10,
8, 12,
6,
6, 9, 11,
9, 3,
5,
2, 15,
1,
3, 15,
4,
2, 11,
6, 7, 12,
0,
5, 14,
3, 8,
5, 0,
0,
0,
6, 13,
5, 10,
9,
8,
1,
7,
1,
8, 10,
0,
7,
6,
13,
7,
1, 14,
// S1
14, 4,
0, 15,
4,
15, 12,
// S2
15,
3, 13,
0, 14,
13,
// S3
10,
13,
13,
1, 10, 13,
// S4
7, 13, 14,
13,
10,
3, 15,
// S5
2, 12,
14, 11,
2,
4,
11,
8, 12,
// S6
12,
10, 15,
8, 11,
6,
0,
9, 14,
0, 9,
4, 9,
6,
3, 15,
3,
4,
8, 15,
5, 1, 13, 12,
6, 10,
3,
0, 11,
2, 8,
1,
7, 11, 4,
2,
5, 14, 12, 11, 15,
5, 10, 14,
2, 12,
0, 6,
9, 8,
7,
4, 15, 14,
3, 11,
5,
2, 12,
3, 0,
6, 9, 10,
1, 2,
8, 5, 11, 12,
4, 15,
5,
6, 15,
9, 0, 12, 11,
6, 10,
1, 13,
8,
0,
3, 4,
7, 13, 15,
7,
1,
9, 4,
2, 12,
3, 14,
5, 11, 12,
1, 10, 14,
5, 2,
8,
2, 14,
7,
9,
4,
3, 15, 13,
0, 14,
9,
1,
4,
2, 12,
1, 11, 10, 13,
7, 10, 11,
4, 7, 13,
7,
8, 5,
5,
6,
1,
8, 15,
0, 15, 10,
5,
9, 12,
7,
1, 14,
2, 13,
6, 15,
0,
3, 9,
6, 3,
9, 10, 4,
1, 10, 15,
4, 2,
9, 2,
7, 12,
6,
9,
8, 0, 13,
5, 6,
3,
4, 14,
7,
0, 11,
1, 13, 14,
8,
0, 14,
5,
6,
3,
5, 11,
3,
8,
5, 2,
8, 12,
7, 0,
9, 5, 15, 10, 11, 14,
3,
4, 10,
1,
7,
1, 13, 11,
6, 0,
6,
8, 13,
2, 12,
2, 14, 15,
0,
8, 13,
3, 12,
9,
7,
5, 10,
6, 1,
4,
7,
0, 11,
4, 11, 13, 12,
8, 1,
3,
4, 10,
9, 1, 10, 14,
7, 14, 10, 15,
7,
9, 5,
3, 5, 12,
6, 8,
0,
0, 15, 14,
2, 15,
8,
6,
5,
2,
9, 2,
3, 12,
9, 14, 15,
4,
3,
// S7
4, 11,
13,
1,
6, 11, 13,
// S8
13,
1, 15, 13,
7, 11,
4,
1, 14,
2,
2,
1, 10,
9, 3, 14,
5,
0, 12,
7,
8, 4,
8, 10,
1,
7,
6, 15, 11,
3,
7,
9, 12, 14,
4, 10, 8, 13, 15, 12,
4, 12,
2,
5, 6, 11,
0, 6, 10, 13, 15,
9,
0,
0, 14,
3,
3, 5,
9, 2,
5, 8,
6, 11
};
(2)主要函数设计说明:
2.1 函数功能:E 盒扩展
函数参数说明:
int input[]:E 置换输入的 32 比特数据
int output[]:E 置换输出 48 比特数据
int table[]:E 盒扩展表
static void DES_Efun(char input[8],char key_in[8],int output[64])
{
int Ip[64]={0};//存储初始置换后的矩阵
int output_1[64]={0};
int subkeys[16][48];
int chartobit[64]={0};
int key[64];
int l[17][32],r[17][32];
CharToBit(input,chartobit,8);//正确,转换为 64 个二进制数的操作正确!
IP(chartobit,Ip,IP_Table);//正确,IP 初始置换!
CharToBit(key_in,key,8);//正确!
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[j-1]);
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[15]);
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,IPR_Table);
2.2
DES 解密
函数功能:完成 DES 加密运算
函数参数说明:
int input[64]:输入需要解密 64 比特
char key_in[8]:输入的解密密钥 8 个字符
char output[8]:输出解密之后明文的 8 个字符
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,8);//正确!
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,8);
2.3 子密钥生成
函数功能:完成 16 轮子密钥生成
函数参数说明:
const int input[64]:输入的 64 比特密钥
int Subkey[16][48]:输出的 16 轮子密钥
static void subKey_fun(const int input[64],int Subkey[16][48])//子密钥生成
{
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);
leftCount += loop_2;
RotateL(c,rotatel_c[i-1],leftCount);
RotateL(d,rotatel_d[i-1],leftCount);
}
else
{
}
}
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);
}
2.4 生成子密钥中循环左移函数
函数功能:完成子密钥扩展的循环左移功能
const int input[28]:循环左移输入 28 比特
int output[28]:循环左移输出 28 比特
int loop:每轮子密钥需要循环左移的位数
static void RotateL(const int input[28],int output[28], int leftCount)//秘钥循环左移
{
int i;
int len = 28 ;
for(i=0;i
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);
Xor(temp,subkey,len);
S(temp,temp_1,S_Box);
P(temp_1,output,P_Table);
};
2.6 IP 初始置换
static
void IP(const int input[64],int output[64],int table[64]);
函数功能:IP 初始置换
函数参数说明:
int input[]:IP 置换输入的 64 比特数据
int output[]:IP 置换输出 64 比特数据
int table[]:IP 置换表
void IP(const int input[64],int output[64],int table[64])//初始 IP 置换
static
{
int i;
for(i=0;i<64;i++)
{
output[i]=input[table[i]-1];//减 1
}
};
(3)主程序设计说明:
主函数负责与用户交互界面的设计,让用户输入明文并存入 MIN 数组中,依次输入 ML1、ML2、ML3 数组,
调用 tripledesEn 函数,并输出明文与运行时间。
int main()
{
long time = 10000000L;
clock_t start, finish;
double Total_time;
int output[64]={0};
char MIN[9]={0};
char MI1[9]={0};
char MI2[9]={0};
char MI3[9]={0};
printf("请输入明文\n");
gets(MIN);
printf("请输入第一个秘钥\n");
gets(MI1);
printf("请输入第二个秘钥\n");
gets(MI2);