徐文兵123067 3DES加密解密软件的实现.docx
《徐文兵123067 3DES加密解密软件的实现.docx》由会员分享,可在线阅读,更多相关《徐文兵123067 3DES加密解密软件的实现.docx(27页珍藏版)》请在冰豆网上搜索。
徐文兵1230673DES加密解密软件的实现
成都信息工程学院
课程设计报告
3DES加密解密的实现
课程名称:
密码算法程序设计
学生姓名:
徐文兵
学生学号:
2009123067
专业班级:
信息对抗技术09级2班
任课教师:
万武南
2011年6月3日
附件:
课程设计成绩评价表
指导老师评阅成绩表
学习与工作态度(30%)
选题意义(10%)
文献综述(10%)
研究水平与设计能力(20%)
课程设计说明说(论文)撰写质量(20%)
设计创新(10%)
总分
指导老师签名:
年月日
课程设计答辩记录及评价表
学生
讲述情况
教师主要
提问记录
学生回答
问题情况
答辩评分
评分项目
分值
评价参考标准
评分
总分
优
良
中
及格
差
选题意义
10
9
8
7
6
4
文献综述
10
9
8
7
6
4
研究水平与设计能力
20
19
17
15
13
10
课程设计说明书(论文)撰写质量
20
19
17
15
13
10
设计创新
10
9
8
7
6
4
答辩效果
30
28
25
22
19
15
答辩小组成员签名
答辩小组组长签名:
年月日
课程设计成绩评定表
成绩汇总
评分项目
评分
比例
分数
课程设计总分
指导老师评分
50%
答辩小组评分
50%
目录
1.背景与意义1
2.系统设计2
2.1系统主要目标2
2.2主要软件需求(运行环境)2
2.3功能模块与系统结构2
3.系统功能程序设计3
3.1基本要求部分3
3.1.1初始置换(IP)3
3.1.2轮结构4
3.1.3逆初始置换(IP-1)9
3.1.4子密钥产生9
3.1.5加密12
3.1.6解密13
3.2较高要求部分14
3.2.1明文分组实现14
3.2.2明文最后分组的填充(ECB模式)15
3.2.3明文分组去掉填充15
3.2.4单个分组的判断(中间过程)16
3.2.5加解密所用时间17
3.3程序界面预览17
4.测试报告18
5.结论19
参考文献20
1.背景与意义
DES(DataEncryptionStandard)算法,于1977年得到美国政府的正式许可,是一种用56位密钥来加密64位数据的方法。
虽然56位密钥的DES算法已经风光不在,而且常有用Des加密的明文被破译的报道,但是了解一下昔日美国的标准加密算法总是有益的,而且目前DES算法得到了广泛的应用,在POS、ATM、磁卡及智能卡(IC卡)、加油站、高速公路收费站等领域,她仍然发挥着余热。
DES是一个对称密码体制,加密和解密使用同一密钥,有效密钥的长度为56位。
同时,一个分组密码,分组长度为64位,明文和密文的长度相同,及64位的明文从算法的一端输入,从另一端输出64位密文;由于DES算法保密性强,到目前为止,除了穷举法外,还没有找到更好的方法破解,因此DES得到了广泛的应用,并成为其他加密方法的典范。
DES-EDE2模式,使用两个互不相同的密钥K1、K2,实现的方式是加密-解密-加密算法,简记EDE。
此方案已在ANSX.9.17和ISO8732中被采用。
DES算法主要研究的是加密与解密算法,解密是加密的逆过程,从加密过的信息中得到明文。
密钥是一串适当长度的字符或数字串,它可以控制加密和解密过程。
通过这次课程设计让我真正的理解了DES加密算法的魅力,它那完全对称的模型让我着迷,同时也让我学到了很多关于密码学相关的知识,加深了对密码学理论中的保密通信模型、各种对称密钥算法的理解和掌握,实现密码理论的应用,为学习后续信息安全方向的课程打下了坚实的基础。
2.系统设计
2.1系统主要目标
基本要求部分:
1.完成一个明文分组的加解密,明文和密钥是ASCII码,且都从文本文件读取。
2.单个分组加密时,输出每次调用DES算法后的值,即加密一组明文输出两组中间值和一组密文,输出同加密,输出的过程保存在文件“加解密过程.txt中”。
较高要求部分:
1.密钥长度不足时填充字符‘0’,过长时自动截取前面8字节部分。
2.明文不止一个分组时,程序自动填充字符‘\0’完成分组,在解密时能够根据算法正确的去掉填充的字符。
3.可以对文本文档以及任意文件进行正确的加解密,且长度不止一个分组。
4.粗略计算程序加解密各种文件所需的时间。
5.程序自动判断文件的大小,如是单个分组即8个字节,就自动输出加解密中间过程。
2.2主要软件需求(运行环境)
本软件使用VC语言编写,编译成功后的EXE文件可以在装有windows系统的任何计算机上使用。
测试平台:
WindowsXPProfessional
使用软件:
VisualC++6.0
2.3功能模块与系统结构
根据DES对称加密算法的实现,对程序进行了一些功能划分:
1、头文件“Printf.h”:
主要负责程序的界面功能,被主函数调用;
2、头文件“key.h”:
由函数“get_key”组成,被主函数调用,从文件获取初始密钥;
3、头文件“IP_zhi_huan.h”:
分别由函数“iP_zhi_huan”和“ip_1_zhi_huan”组成,被头文件“jia_mi.h”中的“E”函数调用,分别实现初始置换和逆初始置换;
4、头文件“jia_mi.h”:
分别由函数“E”和“shi_jz”组成。
函数“E”是核心,被“En_De_crypt.h”中的函数“En”和“De”调用,主要负责单个分组的加解密。
函数“shi_jz”是被函数“E”调用,把二进制转化为十进制以便输出中间过程;
5、头文件“LUN_jie_gou.h”:
由函数“lun_jie_gou”组成,被“jia_mi.h”中的“E”函数调用,主要功能是DES加解密算法中的轮结构;
6、头文件“F_han_shu.h”:
由函数“R_f_han_shu”组成,被“LUN_jie_gou.h”的“lun_jie_gou”函数调用,主要实现轮结构中的F函数部分;
7、头文件“lun_key.h”:
由函数“lun_k”组成,被“LUN_jie_gou.h”中的“lun_jie_gou”函数调用,以实现轮密钥的产生;
8、头文件“En_De_crypt.h”:
由函数“En”和“De”组成,被主函数调用,分别实现多个分组的加密和解密;
9、主函数:
主要负责判断是加密还是解密然后调用不同的函数;
3.系统功能程序设计
3.1基本要求部分
3.1.1初始置换(IP)
原理:
待加密的64比特明文串m,经过IP置换后,得到的64比特串的下标列表如下:
IP初始置换定义表
代码实现:
(IP_zhi_huan.h)
两个数组之间通过一个中间值赋值实现IP初始置换,关键代码如下:
for(i=0;i<64;i++)
{
flag=ip[i]-1;
go[i]=from[flag];
}
此处需要注意的是IP初始置换定义表默认下标是从1开始的,以后的定义表都是如此。
3.1.2轮结构
原理:
以第一轮为例,经过IP初始置换得到的64比特串,前32比特分为左半部分,记为L0,后32比特分为右半部分,记为R0。
R0部分首先根据F函数计算过程给出右半部分的变换过程,即先将R0进行E盒变换,将32比特扩展为48比特。
然后将E盒输出的48比特作为输入与子密钥进行异或(XOR)操作。
然后将输出的48比特作为S盒的输入,进行S盒变换,将48比特压缩为32比特,最后将S盒输出的32比特输入P盒进行置换。
左半部分L0的32比特为上一轮右半部分的32比特L1=R0,而下一轮右半部分为经过P盒作用之后输出的32比特与左半部分L0进行异或(XOR),得到最终的R1的32比特。
一共进行16轮这样的变换。
其图示分别如下图:
轮结构示意图
由图中所示结构可得到每一轮变换可由下面的公式表示:
Li=Ri—1
Ri=Li-1⊕F(Ri-1,Ki)
F函数的结构
E盒定义表
P盒定义表
S盒一共有8个,每个S盒的使用方法如下:
S盒接收到6比特的输入,其中第1个比特和最后1个比特构成的2位二进制为该S盒的行号,中间的4位二进制为该S盒的列号,然后由该S盒的定义表根据行号和列号查表得到对应的值(十进制),转换为二进制即为S盒变换的输出(其定义表省略)。
代码实现:
(LUN_jie_gou.h)
轮结构:
for(i=1;i<=16;i++)//十六轮加解密
{
if(flag1==0)//加密
{
R_f_han_shu(R,f_R,i,k,0);//F函数
}
else//解密
R_f_han_shu(R,f_R,i,k,1);//F函数
for(j=0;j<32;j++)
{
//求左边部分
L[i][j]=R[i-1][j];
//求右边部分
if(L[i-1][j]==f_R[j])
{
R[i][j]=0;
}
else
R[i][j]=1;
}
}
F函数:
//判断加解密,并根据判断调整密钥
if(flag2==0)
FLAG=num;
else
FLAG=17-num;
//E盒扩充
for(i=0;i<48;i++)
{
flag=f_e_he[i]-1;
e_he[i]=from_R[num-1][flag];
}
//E盒输出与轮密钥异或
for(i=0;i<48;i++)
{
if(e_he[i]==from2_key[FLAG][i])
{
f_XOR[i]=0;
}
else
f_XOR[i]=1;
}
//S盒变换压缩
for(i=0;i<48;i++)
{
flag=i/6;
f_XOR_6[flag+1][i%6]=f_XOR[i];
}
for(i=1;i<=8;i++)
{
r=2*f_XOR_6[i][0]+f_XOR_6[i][5];
c=8*f_XOR_6[i][1]+4*f_XOR_6[i][2]+2*f_XOR_6[i][3]+f_XOR_6[i][4];
s_he[i]=f_s_he[i-1][r][c];
for(j=0;j<4;j++)
{
flag=(i-1)*4+3-j;
f_s_he_ejz[flag]=s_he[i]%2;
s_he[i]=s_he[i]/2;
}
}
//P盒置换
for(i=0;i<32;i++)
{
flag=f_p_he[i]-1;
go_f[i]=f_s_he_ejz[flag];
}
3.1.3逆初始置换(IP-1)
原理:
DES算法进行完16轮运算之后,需要进行逆初始置换,逆初始置换正好为初始置换的逆,若一个矩阵进行初始置换之后输出,再进行一次逆初始置换的输出结果为初始置换。
DES的逆初始置换定义表如下:
DES的逆初始置换定义表
代码实现:
(IP_zhi_huan.h)
两个数组之间通过一个中间值赋值实现IP-1逆初始置换,关键代码如下:
for(i=0;i<64;i++)
{
flag=ip_1[i]-1;
go[i]=from[flag];
}
3.1.4子密钥产生
原理:
子密钥产生过程的输入,为用户持有的64比特初始密钥,但若用户只提供56比特,其余8比特由算法提供,分别放在8、16、24、32、40、48、56和64位上。
因此初始密钥中每8位的密钥包含用户提供的7位和DES确定的1位。
用户将初始密钥64位输入到子密钥产生流程中,首先经过密钥置换PC-1,将初始密钥的8比特奇偶校验码去掉。
留下真正的56比特初始密钥。
接着,分为两个28比特分组C0及D0,再分别经过一个循环左移函数,每一半左移1或2位,连接成56比特数据,再按密钥置换PC-2做重排,进行压缩,抛弃8位后,便可输出子密钥的48比特,作为轮结构F函数的密钥输入部分。
该过程如下图所示:
DES轮密钥的产生
PC-1置换选择定义表
循环左移位定义表
注意:
在循环左移位定义表中的迭代顺序是指轮的次序。
置换选择PC-2定义表
代码实现:
(lun_key.h)
for(i=0;i<56;i++)
{
//置换PC-1
flag=k_pc_1[i]-1;
pc_1[i]=from_k[flag];
//分为左右两半
if(i<28)
{
C[0][i]=pc_1[i];
}
else
{
D[0][i-28]=pc_1[i];
}
}
//循环左移位
for(j=1;j<17;j++)
{
if(xun_huan_biao[j]==1)
{
C[j][27]=C[j-1][0];
D[j][27]=D[j-1][0];
for(i=0;i<27;i++)
{
C[j][i]=C[j-1][i+1];
D[j][i]=D[j-1][i+1];
}
}
else
{
C[j][27]=C[j-1][1];
C[j][26]=C[j-1][0];
D[j][27]=D[j-1][1];
D[j][26]=D[j-1][0];
for(i=0;i<26;i++)
{
C[j][i]=C[j-1][i+2];
D[j][i]=D[j-1][i+2];
}
}
//合并并置换选择PC-2
for(i=0;i<28;i++)
{
xun_huan[i]=C[j][i];
xun_huan[28+i]=D[j][i];
}
for(i=0;i<48;i++)
{
flag=k_pc_2[i]-1;
go_k[j][i]=xun_huan[flag];
}
}
3.1.5加密
原理:
前面已经就单个分组的加解密进行了说明,由于本系统是DES-EDE2模式的DES加解密,故下面两节就DES-EDE2加解密模式进行说明。
如下图所示,使用两个互不相同的密钥K1、K2,实现方式为加密—解密—加密算法,简记为EDE。
此方案已在密钥管理标准ANSX.9.17和ISO8732中被采用。
密钥分别为K1=K3,其密文为:
C=EK1(DK2(EK1(P)))
其示意图如下:
三重DES—EDE2模式加密
代码实现:
(En_De_crypt.h)
一重DES的加密:
if(Flag==0)//(加密过程,其中Flag=0表明是加密)
{
ip_zhi_huan(From,p_ip);//初始置换(IP)
lun_jie_gou(p_ip,lun,k,0);//轮结构加密
ip_1_zhi_huan(lun,Go);//逆初始置换
}
三重DES的加密:
E(p,A,K1,0,go);//加密算法E
E(A,B,K2,1,go);//解密算法D
E(B,C,K1,0,go);//加密算法E
3.1.6解密
原理:
在三重DES-EDE2模式中,解密时,密钥顺序正好与加密密钥顺序相反,依次采用解密—加密—解密的顺序,即:
P=DK1(EK2(DK1(C)))
其示意图如下:
三重DES—EDE2模式解密
代码实现:
(En_De_crypt.h)
一重解密的实现:
//(解密过程,即Flag=1)
else
{
ip_zhi_huan(From,p_ip);//初始置换(IP)
lun_jie_gou(p_ip,lun,k,1);//轮结构
ip_1_zhi_huan(lun,Go);//逆初始置换
}
三重DES的实现:
E(p,B,K1,1,go);//解密算法D
E(B,A,K2,0,go);//加密算法E
E(A,p,K1,1,go);//解密算法D
3.2较高要求部分
3.2.1明文分组实现
原理:
由于DES是以8个字节(64比特)为一个分组进行加解密的,故在对多于8个字节的信息加解密时,需要对信息进行进行正确的分组。
最简单的方法便是依照信息的顺序依次以8个字节为单位进行加解密。
代码实现:
(En_De_crypt.h)
//每次读8个字节加密
while(!
feof(fp))
{
count=fread(P,1,8,fp);//按信息的顺序读取字节
…………
if(count==8)//按照读取信息的顺序进行加解密(每次都刚好8字节)
{
…………
3.2.2明文最后分组的填充(ECB模式)
原理:
由于对于任意文件来说,文件的大小是未知不固定的,所以难免遇到最后一个一个分组不是刚好8字节的情况,这时就要对最后一个消息块进行填充。
填充本身是很简单的事情,问题在于有很多种可行的填充方式,如果加密时以某种方式填充,解密时就得理解这种填充方式并去除填充内容,否则很可能解密出来得到的数据就是脏数据。
网上有许多的填充方案,在这里我们选择的是X923填充方式。
即填充为“\0”的字节序列,最后一个字节记录填充的总字节数。
代码实现:
(En_De_crypt.h)
count=fread(P,1,8,fp);//按信息的顺序读取字节
…………….
if(count)//最后一个分组填充
{
//填充
memset(P+count,'\0',7-count);//调用字符串函数完成填充
P[7]=8-count;//最后填充共填充的字节位数
……………
}
3.2.3明文分组去掉填充
原理:
由于密文最后8字节可能有填充的内容,故在解密时,需要对密文的最后8字节(最后一个密文分组)进行一定的判断。
判断方法为:
当检测到是密文的最后一个分组时,先判断最后一个字节,然后根据最后一个字节数来判断需要检查后几个字节位,在判断时,检查后几位字节是否是连续的“\0”字符,如是就代表是填充的内容,或者不是填充的内容。
虽然这样会有一定的误差,但是误差比较小,可忽略不计。
代码实现:
(En_De_crypt.h)
先记录整个密文的长度,以判断是否是最后一个密文分组。
//取文件长度
fseek(fp,0,SEEK_END);//将文件指针置尾
fileLen=ftell(fp);//取文件指针当前位置
rewind(fp);//回到文件头
……………………..
判断填充:
//最后一个分组的解密
if(go[7]<8)//判断末尾是否被填充
{
for(count=8-go[7];count<7;count++)
{
if(go[count]!
='\0')
{
break;//当中间不是连续的“\0”字符时,结束判断
}
}
}
//有填充(即中间是连续的'\0')
if(count==7)
{
fwrite(go,1,8-go[7],fp2);
}
else//无填充
fwrite(go,1,8,fp2);
3.2.4单个分组的判断(中间过程)
原理:
由于在加解密单个分组时,要求输出3DES的加解密过程,故设计此方案。
在此方案中,将把加解密的中间过程全部显示在“加解密过程.txt”文件中,以便查看。
代码实现:
(En_De_crypt.h)
…………………..
//取文件长度
fseek(fp,0,SEEK_END);//将文件指针置尾
fileLen=ftell(fp);//取文件指针当前位置
rewind(fp);//回到文件头
…………………….
//单个分组输出中间过程
if(fileLen==8)
{
fp3=fopen("加解密过程.txt","a");//格式化输出到文件
if(fp3==NULL)
{
printf("cannotopenfile!
\n");
exit(0);
}
……………………
}
……………………………….
3.2.5加解密所用时间
原理:
调用“memory.h”中的clock函数来大致记录程序运行的时间。
精确度为毫秒。
代码实现:
(En_De_crypt.h)
clock_ta,b;
a=clock();
//加解密过程
b=clock();
3.3程序界面预览
4.测试报告
1、单个分组的测试:
K1=comp;K2=computtrewtw;P=learning;
测试结果:
C=剿测试过程(加解密过程.txt):
加密过程
解密过程
5.结论
应用密码学课程设计是在学习密码学理论的基础上,对所学知识加以实践的最好平台。
通过这次课程设计加深了我对密码学理论中有关的对称算法和对称算法的实现模式有了进一步的了解和掌握,以及对密码学理论的应用,为以后信息安全方向的课程打下了坚实的基础。
同时也让我更加熟悉了用C语言开发一个程序的知识,巩固了我的C的理论基础,使我的编程能力有进一步的提升。
在完成程序的过程中,遇到了很多的问题,各式各样的问题都有,但是正是因为这样,所以让我加强了对问题的认识,任何问题成功的坚决掉都需要几步:
发现问题、分析问题、坚决问题和总结问题!
参考文献
[1]刘城霞,蔡英.DES加密技术研究中填充方法的探讨.北京:
北京信息科技大学,2008.
[2]张仕斌,万武南,张金全,孙宣东.应用密码学[M].西安:
西安电子科技大学出版社,2009.
[3]谭浩强.C程序设计(第三版)[M].北京:
清华大学出版社.2008.
[4]朱彦军.DES算法及其在VC++6.0下的实现.航天医学工程研究所四室.
[5]Harry.数据块填充模式.
[6]XX贴吧.C语言吧.
[7]将任意文件转换成C语言的数组.