C语言DES加密算法.docx
《C语言DES加密算法.docx》由会员分享,可在线阅读,更多相关《C语言DES加密算法.docx(16页珍藏版)》请在冰豆网上搜索。
C语言DES加密算法
云南大学软件学院
SchoolofSoftware,YunnanUniversity
成绩
学期:
2011秋季学期
课程名称:
密码技术
任课教师:
学生姓名:
学号:
实验项目:
实验二DES加密算法
联系电话:
电子邮件:
完成提交时间:
年月日
密码技术实验报告
实验项目:
实验二,第2题实现DES对任意文件的加解密
实验要求
(内容)
实现DES对任意文件的加解密,利用控制台对所有文件(中英文文本、符号甚至任意的文件)的加解密。
加解密形式如下:
cipher-e/-dkeyinputfileoutputfile
说明:
对于加密来说,输入文件名就是明文文件,对于解密来说,输入文件名就是密文文件,注意文件读取方式和控制文件结束
控制台编程:
intmain(intargc,char*argv[])
实验环境
操作系统:
win7
编译环境:
MicrosoftVisualStudio2010
实现功能
本次实验达到了题目的要求:
实现了用DES实现控制台对任意文件的加解密,用键盘接收明文(密文)文件路径和密钥,然后再输入需要保存的密文(明文)文件路径,然后就可以把加解密后得到的密明文文件保存该路径下。
程序主要采取对数据的位操作的形式,把明密文文件中的内容以字节为单位读取,每次读取8个byte共65bits,然后使用标准DES的算法依次对读取的64bits明密文进出加解密处理。
主函数的操作也充分体现了程序的可操作性和健壮性,能够让用户自己选择相应的操作,比如加密、解密以及对程序的一些基本情况说明。
但是对文件的路径的输入有比较严格的格式约束。
如:
盘符名:
\\文件名.txt格式错误则会导致文件打开失败,不能进行加解密操作。
数据结构
本次实验的程序较为复杂,涉及对位的操作。
实验过程中用到的主要数据结构为数组和文件型指针,在实验中我定义了2个文件型指针FILE*fp1,*fp2,其中一个指向明文文件,一个指向密文文件。
另外还定义了多个字符数组,如charPlainfpath[260]声明字符数组存储明文文件的文件路径,charCipherfpath[260]声明字符数组存储密文文件的文件路径,charkey[100]声明字符数组存储密钥。
对于读取出来的数据均以unsignedchar的类型进行处理。
这个程序的实现比较复杂的是对位的操作,主要包括取位值、移位和异或等,在对位的操作还主要用到了memcpy函数对unsignedchar类型的字符串进行复制,除此之外没有采用更多的数据结构。
程序流程
程序模块结构图:
开始start
选择操作
解密函数
退出程序
加密函数
用户输入明密文文件路径和密钥
明(密)文文件是否能打开
退出程序
对打开的文件进行操作,每次取出长度为8个byte的明密文。
将8byte的明密文和密钥转换为64bits
明密文进行初始置换IP
密钥进行置换选择1
循环左移和置换选择2产生子密钥
分成左右两部分进入F函数
右半部分在F函数里依次进行扩展置换、与子密钥异或、S盒置换和P置换
经F函数处理的与左半部分异或后成右半部分,原先的右半部分作为左半部分
32bits对换,然后进行逆初始置换
将结果由64bits转换成8byte,然后写入文件保存
main()
函数的调用关系:
Encrypt()
Decrypt()
Explain()
Block_Decrypt()
Block_Encrypt()
L_Shift()
R_Shift()
BToC()
CToB()
F_function()
函数的接口:
voidEncrypt(char*Plainfpath,char*Cipherfpath,unsignedchar*Keys);//加密函数
voidDecrypt(char*Cipherfpath,char*Plainfpath,unsignedchar*Keys);//解密函数
voidBlock_Encrypt(unsignedchar*Plain,unsignedchar*Cipher,unsignedchar*Key);//分组加密函数
voidBlock_Decrypt(unsignedchar*Cipher,unsignedchar*Plain,unsignedchar*Key);//分组加密函数
voidCToB(unsignedchar*C_String,unsignedchar*B_String);//将字符类型转换成二进制类型的函数
voidBToC(unsignedchar*B_String,unsignedchar*C_String);//将二进制类型转换成字符类型的函数
voidL_Shift(unsignedchar*PC_Key,intcount);//加密中循环左移函数
voidR_Shift(unsignedchar*PC_Key,intcount);//解密中循环右移函数
voidF_function(unsignedchar*R_String,unsignedchar*S_Key);//F函数
voidExplain();//程序说明函数
代码与代码分析
主要函数的接口、调用与被调用函数、所实现的功能和实现的主要思路:
intmain(charch):
Function:
为用户提供基本操作,调用加密解密函数。
Calls:
Encrypt(),Decrypt()和Explain()。
CalledBy:
未被其它函数调用。
Input(type)字符型(char)。
Output(type):
无,只是输出“”中的字符串。
Return(type):
整型
Others:
无
Bug:
测试尚未发现
voidEncrypt(char*Plainfpath,char*Cipherfpath,unsignedchar*Keys)
Function:
实现的功能是:
接收明文文件路径和密钥,并打开文件,然后根据对文件的
操作依次从文件中以二进制方式读取字符,并使用DES算法加密,然后将处理过
的二进制字符写入到密文文件中。
实现的主要思路:
首先调用fopen()函数打开文件,对打开的文件进行操作,
调用fseek()函数定位读写指针函数fseek,将文件的读写指针移到文件结束位置,调
用ftell()函数返回fp1指向的文件中的读写指针当前位置,即文件的长度,再调用
rewind()函数将文件读写指针移到文件开始位置。
调用fgetc()从fp1所指向的明文
文件中依次以二进制的方式读取字符,然后调用Block_Encrypt进行加密,并
把结果写入密文文件保存。
此外对于不足8byte的分组将填充*并作标记以便
进行加密。
Calls:
Block_Encrypt()
CalledBy:
main()
Input(type)char类型的数组
Output(type):
char类型的数组
Return(type):
无返回值的类型。
Others:
无
Bug:
测试中尚未发现
voidDecrypt(char*Cipherfpath,char*Plainfpath,unsignedchar*Keys)
Function:
实现的功能是:
接收密文文件路径和密钥,并打开文件,然后根据对文件的
操作依次从文件中以二进制方式读取字符,并使用DES算法解密,然后将处理过
的二进制字符写入到明文文件中。
实现的主要思路:
首先调用fopen()函数打开文件,对打开的文件进行操作,
调用fseek()函数定位读写指针函数fseek,将文件的读写指针移到文件结束位置,调
用ftell()函数返回fp1指向的文件中的读写指针当前位置,即文件的长度,再调用
rewind()函数将文件读写指针移到文件开始位置。
调用fgetc()从fp1所指向的密文
文件中依次以二进制的方式读取字符,然后调用Block_Decrypt()进行解密,并
把结果写入明文文件保存。
此外对于之前有填充标记的分组在解密后应该删除
填充进去的*。
Calls:
Block_Decrypt()
CalledBy:
main()
Input(type)char类型的数组
Output(type):
char类型的数组
Return(type):
无返回值的类型。
Others:
无
Bug:
测试中尚未发现
voidBlock_Encrypt(unsignedchar*Plain,unsignedchar*Cipher,unsignedchar*Key)
Function:
实现的功能是:
接收8个byte的明文,并使用DES算法加密,得到8个byte
的密文。
实现的主要思路:
首先调用CToB()将二进制明文字符与密钥字符转换成
64bits,再依次对64bit的明文进行初始置换、16轮F_function()函数的处理、32bit
对换和逆初始置换得到64bit密文。
在F函数中使用的子密钥是将输入的密钥进
行置换选择1的处理然后在每轮加密中再对密钥进行循环左移和置换选择2的处
理后得到子密钥。
最后调用BToC()将64bit转换成8个byte的密文。
Calls:
CToB(),F_function(),L_Shift和BToC()。
CalledBy:
Encrypt()
Input(type)unsignedchar类型的数组
Output(type):
unsignedchar类型的数组
Return(type):
无返回值的类型。
Others:
无
Bug:
测试中尚未发现
voidBlock_Decrypt(unsignedchar*Cipher,unsignedchar*Plain,unsignedchar*Key);
Function:
实现的功能是:
接收8个byte的密文,并使用DES算法加密,得到8个byte
的明文。
实现的主要思路:
首先调用CToB()将二进制密文字符与密钥字符转换成
64bits,再依次对64bit的密文进行初始置换、16轮F_function()函数的处理、32bit
对换和逆初始置换得到64bit明文。
在F函数中使用的子密钥是将输入的密钥进
行置换选择1的处理然后在每轮解密中再对密钥进行循环右移和置换选择2的处
理后得到子密钥。
最后调用BToC()将64bit转换成8个byte的明文。
Calls:
CToB(),F_function(),R_Shift和BToC()。
CalledBy:
Decrypt()
Input(type)unsignedchar类型的数组
Output(type):
unsignedchar类型的数组
Return(type):
无返回值的类型。
Others:
无
Bug:
测试中尚未发现
voidCToB(unsignedchar*C_String,unsignedchar*B_String)
Function:
将字符(8byte)转换成二进制位值(64bit)
实现的主要思路:
利用表达式*(B_String+(8*i+7-j))=(C_String[i]>>j)&1
对C_String[i]中的字符进行移位操作取出每个位的值赋值给B_String。
Calls:
无
CalledBy:
Block_Encrypt和Block_Decrypt()
Input(type)unsignedchar类型的数组
Output(type):
unsignedchar类型的数组
Return(type):
无
Others:
无
Bug:
测试尚未发现
voidBToC(unsignedchar*B_String,unsignedchar*C_String)
Function:
将二进制位值(64bit)转换成字符(8byte)
实现的主要思路:
利用表达式*(C_String+i)=*(C_String+i)|(*(B_String+
(8*i+j))<<(7-j))将B_String中的每8个值进行移位的等操作构成C_String中的
一个值。
Calls:
无
CalledBy:
Block_Encrypt和Block_Decrypt()
Input(type)unsignedchar类型的数组
Output(type):
unsignedchar类型的数组
Return(type):
无
Others:
无
Bug:
测试尚未发现
voidL_Shift(unsignedchar*PC_Key,intcount)
Function:
将56bit的密钥分两部分左移count位
实现的主要思路:
利用memcpy()对密钥进行复制操作,具体步骤如下:
memcpy(temp,PC_Key,count);
memcpy(PC_Key,PC_Key+count,28-count);
memcpy(PC_Key+(28-count),temp,count);//前28位左移count位
memcpy(temp,PC_Key+28,count);
memcpy(PC_Key+28,PC_Key+(28+count),28-count);
memcpy(PC_Key+(56-count),temp,count);//后28位左移count位
Calls:
无
CalledBy:
Block_Encrypt和Block_Decrypt()
Input(type)unsignedchar类型的数组和int型的值
Output(type):
unsignedchar类型的数组
Return(type):
无
Others:
无
Bug:
测试尚未发现
voidR_Shift(unsignedchar*PC_Key,intcount)
Function:
将56bit的密钥分两部分右移count位
实现的主要思路:
利用memcpy()对密钥进行复制操作,具体步骤如下:
memcpy(temp,PC_Key+(28-count),count);
memcpy(PC_Key+count,PC_Key,28-count);
memcpy(PC_Key,temp,count);//前28位右移count位
memcpy(temp,PC_Key+(56-count),count);
memcpy(PC_Key+(28+count),PC_Key+28,28-count);
memcpy(PC_Key+28,temp,count);//后28位右移count位
Calls:
无
CalledBy:
Block_Encrypt和Block_Decrypt()
Input(type)unsignedchar类型的数组和int型的值
Output(type):
unsignedchar类型的数组
Return(type):
无
Others:
无
Bug:
测试尚未发现
voidF_function(unsignedchar*R_String,unsignedchar*S_Key)
Function:
对明密文的右半部分F函数进行处理,包括扩展置换、与子密钥异或、S
盒置换和P置换
实现的主要思路:
扩展置换利用E表将32位扩展到48位,然后与48位的子
密钥进行异或;S盒置换将48位的明密文分成8个6位块分别对应8个S盒替换
表,然后每个6位块中的第1和6位作为行号,其余的作为列号,在S盒替换表
中找到对应的值,这样将48位压缩到32位,然后再根据置换函数P进行置换操
作。
Calls:
无
CalledBy:
Block_Encrypt和Block_Decrypt()
Input(type)unsignedchar类型的数组
Output(type):
unsignedchar类型的数组
Return(type):
无
Others:
无
Bug:
测试尚未发现
实验输入(可加截图):
实验输入:
先选择加密,然后输入明文文件路径:
c:
\\123.jpg密钥:
yqg需要保存的密文文件路径:
c:
\\12301.jpg
先选择解密,然后输入密文文件路径:
c:
\\12301.jpg密钥:
yqg需要保存的明文文件路径:
c:
\\12302.jpg
结果输出(可加截图):
先选择加密,然后输入明文文件路径:
c:
\\123.jpg密钥:
yqg结果保存了密文文件,路径:
c:
\\12301.jpg但是加密后格式无法打开。
先选择解密,然后输入密文文件路径:
c:
\\12301.jpg密钥:
yqg需要保存的明文文件路径:
c:
\\12302.jpg
实验小结
这次的实验比上次的难度增加了许多,尤其是涉及到取位值以及对位的操作,这个实验花费了很长的时间才基本完成实验的要求,实现了使用DES对任意文件进行加密解密。
通过本次实验,我加深了对DES加密解密算法的的了解,另一方面,我进一步熟悉了C语言的语法知识,主要就是对二进制文件的一些打开关闭和读写操作,另外还有对位的操作等知识。
在这次的实验中对文件打开的方式依然以二进制方式打开,但是因为本次实验中是每次对8个byte的字符进行加密解密操作,因此在读文件的时候使用了fread()函数,每次从文件中读取8个byte的字符,然后用fwrite()函数将8个byte的字符写入文件,另外我把实验中的大部分数组都声明为unsignedchar类型,在对字符串进行复制操作时调用了memcpy函数对字符串进行操作将更为方便。
这次的实验虽然基本完成了实验题目的要求,但是由于个人能力的原因,算法设计得有点复杂,加密解密需要花费太长的时间,因此还需要再改进。