课程:密码学 班级: 姓名: 学号:
成绩: 指导教师: 实验日期:2011/5/25
实验密级: 预习程度: 实验时间:12:50-15:20
仪器组次: 18 必修/选修:必修 实验序号:4
实验名称: 实现DES 分组密码算法的加解密
实验目的与要求:1、掌握DES 分组密码算法的软件实现方法;
2、复习DES 分组密码算法设计的基本原理;
3、能用DES 分组密码算法实现已知明文的加解密
实验仪器:
| 名称 | 型号 | 数量 |
| 计算机 | Lenovo | 1 |
1、求主密钥的扩展密钥前,先输出使用的PC-1 置换和PC-2 置换;
2、对明/密文文件用DES 算法进行加/解密前,先输出确定使用的S 盒和有关置换表;
3、“确定主密钥的扩展密钥”和“对明/密文文件的加/解密”分别编写两个模块,如果时
间不够,可以任选一个模块;
4、确定扩展密钥前,先指出是加密密钥还是解密密钥;
5、密钥扩展的移位的位数可以先添表,但最后一轮移位完后,必须回到初始值c0d0。
6、主密钥长度与明文相一致,需要忽略校验位;
7、能完成任意给定的一个明/密文文件的加/解密;
8、加解密结果正确。
二、实验内容与步骤
下面是程序的部分代码
int main()
{
char MingWen[104];
char target[8];
char InputKey[8];
int text[];
int text_ip[];
int L0[32],Li[32];
int R0[32],Ri[32];
int RE0[48];
int key[];
int keyPC1[56];
int A[28];
int B[28];
int keyAB[56];
int K[16][48];
int RK[48];
int RKS[8];
int SP[32];
int RKSP[32];
int text_end[];
int text_out[14][];
char init[9]={"HTmadeit"};
int CBC[];
int result[13][];
int H[208];
char MiWen[208];
int C[832];
int M[13][8];
char choice;
int t;
int i,j;
int k,l,m,n;
int r[8],c[8];
int flag=1;
printf("欢迎使用DES加密解密\\n\\n");
while(flag)
{printf("A加密,B解密,请选择:\\n");
scanf("%c",&choice);
while(choice!='A'&&choice!='B'&&choice!='a'&&choice!='b')
{printf("对不起,您的输入不合法。请选择A或B,A表示加密,B表示解密。\\n");
scanf("%c",&choice);
}
getchar();
printf("请输入8位密钥:\\n");
gets(InputKey);
while(InputKey[7]=='\\0'||InputKey[8]!='\\0')
{
printf("您输入的密钥位数有误,请重新输入8位密钥:\\n");
gets(InputKey);
}
for(i=0;i<8;i++)
{
int a[8]={0,0,0,0,0,0,0,0};
m=InputKey[i];
for(j=0;m!=0;j++)
{
a[j]=m%2;
m=m/2;
}
for(j=0;j<8;j++)
key[(i*8)+j]=a[7-j];
}
for(i=0;i<56;i++)
keyPC1[i]=key[PC1[i]-1];
for(i=0;i<28;i++) {
A[i]=keyPC1[i];
B[i]=keyPC1[i+28];
}
for(t=0;t<16;t++)
{
if(move[t]==1)
{
n=A[0];
for(i=0;i<27;i++)
A[i]=A[i+1];
A[27]=n;
n=B[0];
for(i=0;i<28;i++)
else
for(i=0;i<8;i++)
target[i]=MingWen[i+(8*l)];
for(i=0;i<8;i++)
{
int a[8]={0,0,0,0,0,0,0,0};
m=target[i];
for(j=0;m!=0;j++)
{a[j]=m%2;
m=m/2;
}
for(j=0;j<8;j++)
text[(i*8)+j]=a[7-j];
}
//for(i=0;i<;i++)
//printf("%d,",text[i]);
//printf("\\n");
//for(i=0;i<;i++)
//printf("%d,",text_out[l][i]);
//printf("\\n");
for(i=0;i<;i++) //CBC模式下前一分组的密文异或当前分组
text[i]=text_out[l][i]^text[i];
//for(i=0;i<;i++)
//printf("%d,",text[i]);
//printf("\\n");
//对每个text进行DES加密
for(i=0;i<;i++) //进行初始换位
text_ip[i]=text[IP[i]-1];
for(i=0;i<32;i++) //分成左右两部分,各32位
{
L0[i]=text_ip[i];
R0[i]=text_ip[i+32];
}
//for(i=0;i<32;i++)
// printf("%d,",L0[i]);
//for(i=0;i<32;i++)
// printf("%d,",R0[i]);
//十六次迭代
for(t=0;t<16;t++)
{
for(i=0;i<48;i++) //将右半部分通过扩展换位表E从32位扩展成48位
RE0[i]=R0[E[i]-1];
//printf("RE0\\n");
//for(i=0;i<48;i++)
//printf("%d,",RE0[i]);
for(i=0;i<48;i++) //RE与K异或运算
RK[i]=RE0[i]^K[t][i];
//printf("\\n");
//for(i=0;i<48;i++)
//printf("%d,",RK[i]);
for(i=0;i<8;i++) //将R和K异或运算的结果通过S位移表
{
r[i]=RK[(i*6)+0]*2+RK[(i*6)+5];
c[i]=RK[(i*6)+1]*8+RK[(i*6)+2]*4+RK[(i*6)+3]*2+RK[(i*6)+4];
}
RKS[0]=S1[r[0]][c[0]];
RKS[1]=S2[r[1]][c[1]];
RKS[2]=S3[r[2]][c[2]];
RKS[3]=S4[r[3]][c[3]];
RKS[4]=S5[r[4]][c[4]];
RKS[5]=S6[r[5]][c[5]];
RKS[6]=S7[r[6]][c[6]];
RKS[7]=S8[r[7]][c[7]];
for(i=0;i<8;i++) //把结果转成32位二进制储存在数组SP中
{
int b[4]={0,0,0,0};
m=RKS[i];
for(j=3;m!=0;j--)
{
b[j]=m%2;
m=m/2;
}
for(j=0;j<4;j++)
SP[j+(i*4)]=b[j];
}
for(i=0;i<32;i++) //将二进制结果再经过一个P盒换位
RKSP[i]=SP[P[i]-1];
for(i=0;i<32;i++) //与前一次的左部异或运算,得到本次迭代的右部
Ri[i]=L0[i]^RKSP[i];
for(i=0;i<32;i++)
{
L0[i]=R0[i];
R0[i]=Ri[i];
}
}
else if(choice=='B'||choice=='b')
{
printf("请输入密文内容:\\n");
gets(MiWen);
for(i=0;i<208;i++)
H[i]=0;
for(i=0;MiWen[i]!='\\0';i++) //将十六进制密文转化成十进制存放在数组H中
{
if(MiWen[i]>='0'&&MiWen[i]<='9')
H[i]=MiWen[i]-'0';
else if(MiWen[i]>='A'&&MiWen[i]<='F')
H[i]=MiWen[i]-'A'+10;
else if(MiWen[i]>='a'&&MiWen[i]<='f')
H[i]=MiWen[i]-'a'+10;
else
{
printf("请输入用十六进制表示的密文内容:\\n");
gets(MiWen);
i=0;
}
}
n=i; //密文有n个字符
if(n%16!=0)
{
printf("对不起,您输入的密文不正确,请确认密文的内容,密文的字符数应是16的倍数。\\n");
printf("请输入密文内容:\\n");
gets(MiWen);
for(i=0;i<208;i++)
H[i]=0;
for(i=0;MiWen[i]!='\\0';i++) //将十六进制密文转化成十进制存放在数组H中
{
if(MiWen[i]>='0'&&MiWen[i]<='9')
H[i]=MiWen[i]-'0';
else if(MiWen[i]>='A'&&MiWen[i]<='F')
H[i]=MiWen[i]-'A'+10;
else if(MiWen[i]>='a'&&MiWen[i]<='f')
H[i]=MiWen[i]-'a'+10;
}
}
for(i=0;i int he[4]={0,0,0,0}; for(j=3;H[i]!=0;j--) { he[j]=H[i]%2; H[i]=H[i]/2; } for(j=0;j<4;j++) C[j+(i*4)]=he[j]; } //for(i=0;i<130;i++) // printf("%d,",C[i]); //printf("\\n"); k=n/16; for(l=0;l for(i=0;i<;i++) //将每个分组对应的位二进制密文放到text_out中 text_out[l+1][i]=C[i+(l*)]; //for(i=0;i<;i++) // printf("%d,",text_out[l][i]); //printf("\\n"); //对每个text进行DES解密 for(i=0;i<;i++) //进行初始换位 text_ip[i]=text_out[l+1][IP[i]-1]; //for(i=0;i<;i++) //printf("%d,",text_ip[i]); //printf("\\n"); for(i=0;i<32;i++) //分成左右两部分,各32位 { L0[i]=text_ip[i]; R0[i]=text_ip[i+32]; } //for(i=0;i<32;i++) // printf("%d,",L0[i]); //for(i=0;i<32;i++) // printf("%d,",R0[i]); //CBC模式下的解密 for(i=0;i<;i++) //前一分组的密文异或当前分组所得明文的二进制放到result中 result[l][i]=text_out[l][i]^text[i]; } for(i=0;i<(n/16);i++) //将二进制转成十进制 for(j=0;j<8;j++) M[i][j]=result[i][(j*8)+0]*128+result[i][(j*8)+1]*+result[i][(j*8)+2]*32+result[i][(j*8)+3]*16+result[i][(j*8)+4]*8+result[i][(j*8)+5]*4+result[i][(j*8)+6]*2+result[i][(j*8)+7]; printf("您的文件经过DES解密后的明文是:\\n"); for(i=0;i<(n/16);i++) for(j=0;j<8;j++) printf("%c",M[i][j]); printf("\\n\\n\\n"); } flag=0; printf("是否继续?\\n"); printf("Y继续,N退出,请选择:\\n"); scanf("%c",&choice); while(choice!='Y'&&choice!='N'&&choice!='y'&&choice!='n') {printf("对不起,您的输入不合法。请选择Y或N,Y表示继续使用本程序,N表示退出。\\n"); scanf("%c",&choice); } getchar(); if(choice=='Y'||choice=='y') flag=1; } } 三、实验体会 在这次实验中我学到很多东西,了解如何实现DES算法。 首先,和以前实验相比,这次实验比较难,程序代码很长,需要花大工夫才能理解,最后还是在同学的帮助下程序才实现。 就程序本身来说,由于步骤比较多,所以逻辑要很清楚,在明密文的转换中产生各种错误,需要耐心细心检查。 通过这次实验使我对知识本身有着更深的了解,希望以后实验能学到更多知识。下载本文