3DES加密解密的实现.docx
《3DES加密解密的实现.docx》由会员分享,可在线阅读,更多相关《3DES加密解密的实现.docx(25页珍藏版)》请在冰点文库上搜索。
3DES加密解密的实现
目录
1.背景与意义4
2.系统设计4
2.1系统主要目标4
2.2主要软件需求(运行环境)5
2.3功能模块与系统结构5
3系统功能程序设计6
3.1基本要求部分6
3.1.1相关格式转换函数6
3.1.2生成子密钥7
3.1.3DES中的轮结构10
IP逆置换11
E盒扩展11
P盒置换12
S盒置换13
左右交换14
3.1.4DES加密单个分组14
3.1.5DES解密单个分组16
3.1.63DES加密单个分组17
3.1.73DES解密单个分组17
3.2程序界面预览18
4.测试报告21
5.结论21
参考文献21
1.背景与意义
通过《应用密码学》这门课程学习了理论上的DES的加密和解密算法以后,通过C++类的思想和VC++图形界面的展示,通过实践实现基本的DES算法以及3DES(EDE2)。
并且通过此类派生出来的其他类,也可以再今后的场合中,包括IM软件,都可以调用此类来进行功能的扩展。
所以说DES核心算法的实现,是相当有意义的。
本程序主要实现了3DES(EDE2)基本的文本加密。
文本加密可以是8位以内的字符。
2.系统设计
2.1系统主要目标
基本要求部分:
根据题目要求完成了哪些内容,具体的列举出来
1.在深入理解DES加密/解密算法理论的基础上,设计一个3DES(EDE2模式)加密/解密软件系统;
2.完成一个明文分组的加解密,明文和密钥是ASCII码,且都从文本文件读取。
3.进行加密时,要求输出每次调用DES算法后的值,即加密一组明文输出两组中间值和一组密文,且能够进行正确的解密,输出同加密;
4.要求提供所设计系统的报告及完整的软件;
5.提供良好的用户界面。
较高要求部分:
1.如果明文不止一个分组,程序能完成分组,然后加密;密钥长度不足时能进行填充,过长是自动截取前面部分。
2.要求明文输入是文本文档,以及任意文件,且长度不止一个分组。
进行加密后,能够进行正确的解密;
3.程序代码有比较好的结构,如用类进行封装,通过调用类的成员函数实现加密解密功能等;
4.对加密大文件的考虑;
5.多线程的使用。
2.2主要软件需求(运行环境)
本软件适用VC语言编写,编译成功后的EXE文件可以在装有windows系统的任何计算机上使用。
测试平台:
Windows7(64)
使用软件:
VisualStudio2008
2.3功能模块与系统结构
本程序由于时间比较紧凑,自己写的函数没有封装到类里,以后有时间会继续完善代码。
以上是我本人写的18个函数,对于功能模块的进行了比较良好的划分。
CDESDlg是一个MFC自动生成的类。
其主要功能是实现了连接界面和内部核心代码之间的桥梁。
3系统功能程序设计
3.1基本要求部分
3.1.1相关格式转换函数
概述:
在MFC编程中,对于编辑框内容的获取,与文件的操作使用char型数据都是比较方便的,考虑到如此,过程中会有许多相互转化的函数。
因此我先把我用到的转换函数列出。
intByteToBit(charch,charbit[8])
{
inti;
for(i=0;i<8;i++)
{
*(bit+(7-i))=(ch>>i)&1;
}
return0;
}
函数解释:
例如字符为’c’,ascii码为99,八位二进制为01100011,首先bit[0]的值是ch右移0位并与1,得1,bit[1]的值是ch右移1位并与1,得1,以此类推得到八位字符串11000110,在进行倒置得到目的字符的二进制形式。
intChar8ToBit64(charch[8],charbit[64])
{
inti;
for(i=0;i<8;i++)
{
ByteToBit(*(ch+i),bit+(i<<3));
}
return0;
}
函数解释:
0左移3为变为0,1左移3位变为8,2变16,3变24,4变32,5变40,6变48,7变56;
调用ByteToBit将每个字符的二进制按顺序赋给各个bit数组。
intBit64ToChar8(charbit[64],charch[8])
{
inti,j=0,k=0;
charbit1[8][8];
for(i=0;i<8;i++)
{
ch[i]=0;
}
for(i=0;i<64;i++)
{
bit1[j][k]=bit[i];
k++;
if((i+1)%8==0)
{
j+=1;
k=0;
}
}
for(i=0;i<8;i++)
{
for(j=0;j<8;j++)
{
ch[i]+=bit1[i][j]*pow(2.0,(7-j));
}
}
return0;
}
}
函数解释:
将64位的2进制变成8位的字符串,从bit[64]中读取,存放在ch[8]中。
3.1.2生成子密钥
概述:
子密钥产生过程的输入,为用户持有的64比特初始密钥,经过选择置换PC-1(permuted
Choice1),得到56bit,接着分为2个28bit分组,在进行一个循环左移位,再按PC-2进行压缩,得到子密钥。
intDES_MakeSubKeys(charkey[64],charsubKeys[16][48])//subKeys[16][48]存储每一轮的密钥
{
chartemp[56];//临时存储
inti;
DES_PC1_Transform(key,temp);//PC_1,将key[64]转到temp[56]里存放
for(i=0;i<16;i++)
{
DES_ROL(temp,Move_Left[i]);//循环移位
DES_PC2_Transform(temp,subKeys[i]);//PC_2
}
return0;
}
函数解释:
输入初始密钥,产生16轮的子密钥,存放在subKeys[16][48]这个二维数组里,调用了DES_PC1_Transform(charkey[64],chartempbts[56]),DES_PC2_Transform(charkey[56],char*tempbts),DES_ROL(chardata[56],inttime)三个函数
intDES_PC1_Transform(charkey[64],chartempbts[56])//key[64]密钥,经过PC_1置换后存放在tempbts[56]中
{
inti;
for(i=0;i<56;i++)
{
tempbts[i]=key[PC_1[i]-1];
}
return0;
}
函数解释:
从key[64]中读取数据,经过PC_1置换后存放在tempbts[56]中
代码:
intDES_PC2_Transform(charkey[56],char*tempbts)//同上
{
inti;
for(i=0;i<48;i++)
{
tempbts[i]=key[PC_2[i]-1];
}
return0;
}
函数解释:
查PC-2表,置换密钥中的值
intDES_ROL(chardata[56],inttime)
{
inti;
//chartemp[56];
chardeposit[2];//存放要循环的数
switch(time)
{
case1:
//左移位为1时
deposit[0]=data[0];//前28位的左移位
for(i=1;i<28;i++)
{
data[i-1]=data[i];
}
data[27]=deposit[0];
deposit[0]=data[28];//后28位的左移位
for(i=29;i<56;i++)
{
data[i-1]=data[i];
}
data[55]=deposit[0];
break;
case2:
//左移位为2时
deposit[0]=data[0];//前28位
deposit[1]=data[1];
for(i=2;i<28;i++)
{
data[i-2]=data[i];
}
data[26]=deposit[0];
data[27]=deposit[1];
deposit[0]=data[28];//后28位,temp[28]-temp[55]
deposit[1]=data[29];
for(i=30;i<56;i++)
{
data[i-2]=data[i];
}
data[54]=deposit[0];
data[55]=deposit[1];
break;
}
return0;
}
函数解释:
这里用了一个switch语句,判断time传递进来的是1还是2,然后申明了一个deposit数组来存放要移位的数。
3.1.3DES中的轮结构
IP置换:
intDES_IP_Transform(chardata[64])
{
inti;
chartemp[64];
for(i=0;i<64;i++)
{
temp[i]=data[IP_CHANGE_Table[i]-1];
}
memcpy(data,temp,64);
return0;
}
函数解释:
从数组data[64]中读取数据,进行查表操作IP置换。
IP逆置换
intDES_IP_1_Transform(chardata[64])
{
inti;
chartemp[64];
for(i=0;i<64;i++)
{
temp[i]=data[IP_BACK_Table[i]-1];
}
memcpy(data,temp,64);
return0;
}
函数解释:
查IP_BACK_Table表,进行IP逆置换操作
E盒扩展
intDES_E_Transform(chardata[48])
{
inti;
chartemp[48];
for(i=0;i<48;i++)
{
temp[i]=data[E_Table[i]-1];
}
memcpy(data,temp,48);
return0;
}
函数解释:
查E_Table表,进行E盒扩展操作
异或
intDES_XOR(charR[48],charL[48],intcount)
{
inti;
for(i=0;i{
R[i]^=L[i];
}
return0;
}
函数解释:
输入要异或的数目,左右数组逐个进行异或操作。
存放在R的数组里。
P盒置换
intDES_P_Transform(chardata[32])
{
inti;
chartemp[32];
for(i=0;i<32;i++)
{
temp[i]=data[P_Table[i]-1];
}
memcpy(data,temp,32);
return0;
}
函数解释:
通过查找P_Table表完成P盒置换操作
S盒置换
intDES_SBOX(chardata[48])
{
chartemp[8][6];
charrowtemp[2];//用数组存放行的头尾两个数字
charlinetemp[4];//存放中间的4个数字
inti,i1=3,j,k=0;
introw,line;
intmedian;
for(i=0;i<8;i++)
{
for(j=0;j<6;j++)
{
temp[i][j]=data[k];
k++;
}
}
for(i=0;i<8;i++)
{
rowtemp[1]=temp[i][0];
rowtemp[0]=temp[i][5];
row=int(rowtemp[1]*pow(2.0,1)+rowtemp[0]*pow(2.0,0));//转10进制
linetemp[0]=temp[i][4];
linetemp[1]=temp[i][3];
linetemp[2]=temp[i][2];
linetemp[3]=temp[i][1];
line=int(linetemp[0]*pow(2.0,0)+linetemp[1]*pow(2.0,1)+linetemp[2]*pow(2.0,2)+linetemp[3]*pow(2.0,3));//转10进制
median=S_Table[i][row][line];
//转2进制(从后面开始向前存储)
for(j=0;j<4;j++)
{
data[i1-j]=median%2;
median=median/2;
}
i1=i1+4;
}
return0;
}
函数解释:
将输入的48位数组的每6位进行分组,第1*2加上第6位为对应的行号,中间四位分别乘8,4,2,1的加和为对应的列号,进行查表置换得到ascii值,例如i=0,查s盒第一个表,行号keyXORri_1[0]*2+keyXORri_1[5],列号为keyXORri_1[1])*8+(keyXORri_1[2])*4+(keyXORri_1[3])*2+keyXORri_1[4]]
左右交换
intDES_Swap(charleft[32],charright[32])
{
chartemp[32];
memcpy(temp,left,32);
memcpy(left,right,32);
memcpy(right,temp,32);
return0;
}
函数解释:
通过memcpy这个系统函数来进行左右交换操作。
3.1.4DES加密单个分组
函数名:
DES_EncryptBlock
参数:
(charplainBlock[9],charsubKeys[16][48],charcipherBits[64])
结论:
实现了加密单个分组的功能
代码:
intDES_EncryptBlock(charplainBlock[9],charsubKeys[16][48],charcipherBits[64])
{
charplainBits[64]={0};
charcopyRight[48]={0};
inti;
//转进制
Char8ToBit64(plainBlock,plainBits);
//IP置换
DES_IP_Transform(plainBits);
for(i=0;i<16;i++)
{
//实现右半边操作
memcpy(copyRight,plainBits+32,32);
//E盒扩充(输出位)
DES_E_Transform(copyRight);
//右半边和每一轮子密钥异或(输出位)
DES_XOR(copyRight,subKeys[i],48);
//S盒置换(输出位)
DES_SBOX(copyRight);
//P盒置换(输出位)
DES_P_Transform(copyRight);
//右边和左边进行异或(存放在plainBits)
DES_XOR(plainBits,copyRight,32);
//第轮不交换
if(i!
=15)
{
DES_Swap(plainBits,plainBits+32);
}
}
//IP逆置换
DES_IP_1_Transform(plainBits);
memcpy(cipherBits,plainBits,64);
return0;
}
3.1.5DES解密单个分组
函数名:
DES_DecryptBlock
参数:
(charcipherBits[64],charsubKeys[16][48],charplainBlock[9])
结论:
实现了解密单个分组的功能
代码:
intDES_DecryptBlock(charcipherBits[64],charsubKeys[16][48],charplainBlock[9])
{
inti;
charcopyRight[48]={0};
//IP置换
DES_IP_Transform(cipherBits);
for(i=15;i>=0;i--)
{
//实现右半边操作
memcpy(copyRight,cipherBits+32,32);
//E盒扩充(输出位)
DES_E_Transform(copyRight);
//右半边和每一轮子密钥异或(输出位)
DES_XOR(copyRight,subKeys[i],48);
//S盒置换(输出位)
DES_SBOX(copyRight);
//P盒置换(输出位)
DES_P_Transform(copyRight);
//右边和左边进行异或(存放在plainBits)
DES_XOR(cipherBits,copyRight,32);
//第轮不交换
if(i!
=0)
{
DES_Swap(cipherBits,cipherBits+32);
}
}
//IP逆置换
DES_IP_1_Transform(cipherBits);
Bit64ToChar8(cipherBits,plainBlock);
return0;
}
3.1.63DES加密单个分组
函数名:
DES_EncryptBlock3
参数:
(charplainBlock[9],charsubKeys1[16][48],charsubKeys2[16][48],charcipherBits[64])
结论:
实现了3DES(EDE2)模式加密单个分组的功能
代码:
intDES_EncryptBlock3(charplainBlock[9],charsubKeys1[16][48],charsubKeys2[16][48],charcipherBits[64])
{
//key1加密
DES_EncryptBlock(plainBlock,subKeys1,cipherBits);
//key2解密
DES_DecryptBlock(cipherBits,subKeys2,plainBlock);
//key1加密
DES_EncryptBlock(plainBlock,subKeys1,cipherBits);
return0;
}
3.1.73DES解密单个分组
函数名:
DES_DecryptBlock3
参数:
(charcipherBits[64],charsubKeys1[16][48],charsubKeys2[16][48],charplainBlock[9])
结论:
实现了3DES(EDE2)模式解密单个分组的功能
代码:
intDES_DecryptBlock3(charcipherBits[64],charsubKeys1[16][48],charsubKeys2[16][48],charplainBlock[9])
{
//key1解密
DES_DecryptBlock(cipherBits,subKeys1,plainBlock);
//key2加密
DES_EncryptBlock(plainBlock,subKeys2,cipherBits);
//key1解密
DES_DecryptBlock(cipherBits,subKeys1,plainBlock);
return0;
}
3.2程序界面预览
说明……………………
从文件中读出数据:
点击浏览可以选择读取文件
输出时要选择输出模式,有两种,分别是二进制输出和字符串输出,
这是二进制输出:
这是解密二进制输出:
这是解密:
4.测试报告
本程序经过测试,文本加密,任意字符,只要是电脑能显示出来的字符都能加密,而且轮密钥显示正常,也能解密回原来的结果。
但是由于没有做较高要求,所以只能加密和解密一个分组长度的字符。
5.结论
DES加密虽然已经过时了,但是通过本程序写的类的扩展性非常好,可以通过这个DESCORE核心代码扩展出很多DES的不同算法,当然也可以适用于不同加密模式。
本程序的内核结构非常清晰,但是由于时间原因,在服务类的设计上还有所欠缺。
我也学会了灵活使用MSDN查阅各种API和各种函数的用法。
通过进一步分析DES算法的特性,同时也对数据在内存中的存储有了更进一步的认识。
对MFC的windows编程有了进一步的认识。
但是由于基础还不够扎实,在写代码的时候也会遇到很多基础问题。
所以通过这次课程设计,使我明白了凡是都要把基础打牢固了,才能有更进一步的发展,基础不稳,知识面再广,也只是空中楼阁。
今后,我相信我还会再改写一遍3DES在这次的基础上会完善代码。
参考文献
[1]JeffreyRichter,ChristopheNasarre.Windows核心编程(第五版)[M]清华大学出版社 2008
[2]StanleyB.Lippman,JoseeLajoie,BarbrarE.Moo.C++Primer(第四版)[M]人民邮电出版社(第四版) 2006
[3]张仕斌,万武南,张金全,孙宣东.应用密码学[M]西安电子科技大学出版社2009
[4]王艳萍,张铮.Windows程序设计(第二版)[M]人民邮电出版社 2008
[5]孙鑫,余安萍.VC++深入详解[M]电子工业出版社2006