实验一对称密钥密码加密解密实验实验学时:2学时实验类型:设计实验要求:必修【实验目的】1、掌握对称密钥密码体制的基本概念;2、掌握对称密钥密码体制加密/解密的工作原理;3、重点掌握DES密码算法加密/解密的基本原理;4、通过用DES算法对实际的数据进行加密/解密运算来深刻了解DES的运行原理。
【实验内容】1、根据DES密码算法原理,用Turbo C2.0或Visual C++6.0设计编写符合DES密码算法思想的加密/解密程序。
【实验环境】1、操作系统:Windows9x/NT/2000/XP2、编程软件:Turbo C2.0或Visual C++6.0【实验原理】1、DES算法工作的基本原理:DES是基于Feistel密码结构的分组密码,其入口参数有三个:key、data、mode。
其中,key为加密/解密时使用的密钥;data为加密/解密的数据;mode为其工作模式:当模式为加密模式时,明文按照64位进行分组,形成明文分组,此时key用于对数据加密;当模式为解密模式时,key用于对64位的密文分组进行解密,以恢复明文。
2、DES算法共进行16轮迭代操作,每轮中都使用相同的轮函数F,如下:F(Ri-1,Ki)=p_box(S_boxes(Expand(Ri-1) ⊕ Ki))整个算法的流程如图所示:DES加密算法流程图(一)、密钥生成1、生成种子密钥K使用密钥流生成器生成64位(8个字节)的种子密钥K,每个字节的第8位作为奇偶校验位,不参与实际运算中子密钥的生成过程。
2、生成每一轮迭代中使用的子密钥ki。
(1) 根据PC-1置换进行种子密钥K的变换,舍弃64位种子密钥K中的8个奇偶校验位,得到56位的密钥。
(2) 将变换后的密钥分为左右两部分各28位,分别称为C0和D,即PC-1(K)=C 0D0。
(3) 生成16个子密钥ki,1≤i≤16。
(i) 将Ci 、Di循环左移1位或2位,根据i值由“循环左移表”决定循环左移的位数,即计算C i=LS i(C i-1)和D i=LS i(D i-1),其中,LS表示循环左移。
(ii) 将循环左移后的Ci 和Di作为一个56位的整体按置换表PC-2进行变换,得到本轮所使用的48位子密钥ki,即k i=PC-2(C i D i)(1≤i≤16)。
(二)、处理64位数据1、取得64位明文分组数据m,如果数据长度不足64位,应该将其扩展为64位(例如补零)。
2、将64位明文分组数据m按初始置换表IP进行变换,获得64位的m,并将m0分为左右两部分,前面32位记为L,后面32位记为R,即 m0=IP(m)=L0R0。
3、用16个子密钥ki(1≤i≤16)加密数据。
所用变换公式为:F(Ri-1,Ki)=p_box(S_boxes(Expand(Ri-1) ⊕ Ki))(1) 将32位的Ri-1按扩展置换E扩展成48位;(2) 异或Ri-1和ki;(3) 将异或后的结果分为8个6位长的部分,第1位到第6位称为S[1],第7位到第12位称为S[2],依此类推,第43位到第48位称为S[8];(4) 按S盒的变换原理变换所有的S[j],1≤j≤8。
每一个S盒都是将输入的6位数据经过处理后转换成4位数据输出。
(5) 将S[1]到S[8]的输出组合成32位数据,按P置换进行变换,变换的结果就是轮函数F。
(6) 异或轮函数F和Li-1,结果就是Ri,即R i=L i-1⊕ F(R i-1,K i)(7) L i=R i-1(8) 循环执行轮函数F,直到K16被变换完成。
4、第16轮迭代结束后左、右部分各是L16和R16,将左右部分交换,作为64位的预输出,即L17=R16,R17=L16。
5、将变换后的R16L16按逆初始置换IP-1进行变换得到最后的结果,即为密文,即c=IP-1(R16L16 )。
【实验步骤】本实验为设计型实验,要求学生自己根据实验原理,自行设计实验步骤,利用Turbo C2.0或Visual C++6.0进行编程,实现对一个文件进行加密和解密。
【思考题】1、DES算法中大量的置换运算的作用是什么?2、DES算法中S盒变换的作用是什么?3、通过查阅相关资料了解目前破解DES算法的基本原理或方法。
附:例程#include <stdio.h>#include <string.h>#include <windows.h>#include <conio.h>#include "Schedle.h"//该头文件中包含了DES算法中所使用的全部变换表class CShift{public:DWORDLONG mask[16];int step[16];CShift(){for(int i=0;i<16;i++){step[i]=2;//其余轮的迭代中,循环左移的位数是2位mask[i]=0xc000000;}step[0]=step[1]=step[8]=step[15]=1;//第1、2、9、16轮迭代中,循环左移的位数是1位mask[0]=mask[1]=mask[8]=mask[15]=0x8000000;}};class CDES{public:CDES(){m_dwlKey=0;m_dwlData=0;ConvertTableToMask(dwlKey_PC_1,64);ConvertTableToMask(dwlKey_PC_2,56);ConvertTableToMask(dwlData_IP,64);ConvertTableToMask(dwlData_Expansion,32);ConvertTableToMask(dwlData_FP,64);ConvertTableToMask(dwlData_P,32);Generate_S();}void EncryptKey(char *);unsigned char* EncryptData(unsigned char *);unsigned char* DescryptData(unsigned char*);private:void ConvertTableToMask(DWORDLONG *,int);void Generate_S(void);DWORDLONG ProcessByte(unsigned char*,BOOL);DWORDLONG PermuteTable(DWORDLONG,DWORDLONG*,int);void Generate_K(void);void EncryptKernel(void);DWORDLONG Generate_B(DWORDLONG,DWORDLONG*);DWORDLONG dwlData_S[9][4][16];CShift m_shift;DWORDLONG m_dwlKey;DWORDLONG m_dwlData;DWORDLONG m_dwl_K[17];};void CDES::EncryptKey(char *key){//输入种子密钥printf("\n请输入种子密钥: %s\n",key);m_dwlKey=ProcessByte((unsigned char*)key,TRUE);m_dwlKey=PermuteTable(m_dwlKey,dwlKey_PC_1,56);Generate_K();//16轮的子密钥生成函数}void CDES::Generate_K(void){DWORDLONG C[17],D[17],tmp;C[0]=m_dwlKey>>28; D[0]=m_dwlKey&0xfffffff;//在16轮迭代中,每一轮的Ci和Di分别进行循环左移后,再组合成56位的数据经过PC-2置换得到本轮的子密钥kifor(int i=1;i<=16;i++){tmp=(C[i-1]&m_shift.mask[i-1])>>(28-m_shift.step[i-1]);C[i]=((C[i-1]<<m_shift.step[i-1])|tmp)&0x0fffffff; tmp=(D[i-1]&m_shift.mask[i-1])>>(28-m_shift.step[i-1]);D[i]=((D[i-1]<<m_shift.step[i-1])|tmp)&0x0fffffff; m_dwl_K[i]=(C[i]<<28)|D[i];m_dwl_K[i]=56位m_dwl_K[i]=PermuteTable(m_dwl_K[i],dwlKey_PC_2,48);}}DWORDLONG CDES::ProcessByte(unsigned char *key,BOOL shift){unsigned char tmp;DWORDLONG byte=0;int i=0;while(i<8){while(*key){if(byte!=0)byte<<=8;tmp=*key;if(shift)tmp<<=1;i++;key++;}if(i<8)byte<<=8;i++;}return byte;}DWORDLONG CDES::PermuteTable(DWORDLONG dwlPara,DWORDLONG* dwlTable,int nDestLen){ int i=0;DWORDLONG tmp=0,moveBit;while(i<nDestLen){moveBit=1;if(dwlTable[i]&dwlPara){moveBit<<=nDestLen-i-1;tmp|=moveBit;}i++;}return tmp;}void CDES::ConvertTableToMask(DWORDLONG *mask,int max){int i=0;DWORDLONG nBit=1;while(mask[i]!=0){nBit=1;nBit<<=max-mask[i];mask[i++]=nBit;}}void CDES::Generate_S(void){//S盒变换int i;int j,m,n;m=n=0;j=1;for(i=0;i<512;i++){dwlData_S[j][m][n]=S_box[i];n=(n+1)%16;if(!n){if(!m)j++;}}}unsigned char* CDES::EncryptData(unsigned char *block){//加密函数unsigned char *EncrytedData=new unsigned char(15);printf("\n输入的明文分组为: %s\n",block);m_dwlData=ProcessByte(block,0);m_dwlData=PermuteTable(m_dwlData,dwlData_IP,64);EncryptKernel();//调用轮函数DWORDLONG bit6=m_dwlData;for(int i=0;i<11;i++){EncrytedData[7-i]=(unsigned char)(bit6&0x3f)+46;bit6>>=6;}EncrytedData[8]='\0';printf("\n加密后的密文为: %s",EncrytedData);for(i=0;i<8;i++){EncrytedData[7-i]=(unsigned char)(m_dwlData&0xff);m_dwlData>>=8;}EncrytedData[8]='\0';return EncrytedData;}void CDES::EncryptKernel(void){ //轮函数int i=1;DWORDLONG L[17],R[17],B[9],EK,PSB;L[0]=m_dwlData>>32;R[0]=m_dwlData&0xffffffff;//16轮迭代for(i=1;i<=16;i++){L[i]=R[i-1];R[i-1]=PermuteTable(R[i-1],dwlData_Expansion,48); EK=R[i-1]^m_dwl_K[i];PSB=Generate_B(EK,B);R[i]=L[i-1]^PSB; }R[16]<<=32;m_dwlData=R[16]|L[16];m_dwlData=PermuteTable(m_dwlData,dwlData_FP,64);}unsigned char* CDES::DescryptData(unsigned char *desData){int i=1;unsigned char *DescryptedData=new unsigned char(15);DWORDLONG L[17],R[17],B[9],EK,PSB;DWORDLONG dataPara;dataPara=ProcessByte(desData,0);dataPara=PermuteTable(dataPara,dwlData_IP,64);R[16]=dataPara>>32;L[16]=dataPara&0xffffffff;for(i=16;i>=1;i--){R[i-1]=L[i];L[i]=PermuteTable(L[i],dwlData_Expansion,48); EK=L[i]^m_dwl_K[i];PSB=Generate_B(EK,B);L[i-1]=R[i]^PSB;}L[0]<<=32;dataPara=L[0]|R[0];dataPara=PermuteTable(dataPara,dwlData_FP,64);for(i=0;i<8;i++){DescryptedData[7-i]=(unsigned char)(dataPara&0xff);dataPara>>=8;}DescryptedData[8]='\0';printf("\n\n解密后的明文为: %s\n",DescryptedData);return DescryptedData;}DWORDLONG CDES::Generate_B(DWORDLONG EKPara,DWORDLONG *block){int i,m,n;DWORDLONG tmp=0;for(i=8;i>0;i--){//将48位数据按照6位一组进行分组后分别进入8个S盒中 block[i]=EKPara&0x3f;m=(int)(block[i]&0x20)>>4;m|=block[i]&0x01;n=(int)(block[i]<<1)>>2;block[i]=dwlData_S[i][m][n];EKPara>>=6;//当前的6位数据根据i值选择进入某一个S盒中进行变换 }//8个S盒依次变换for(i=1;i<=8;i++){tmp|=block[i];tmp<<=4;//每一个S盒将6位输入转换为4位输出}tmp>>=4;tmp=PermuteTable(tmp,dwlData_P,32);return tmp;}void main(void){CDES des;des.EncryptKey("12345678");unsigned char *result=des.EncryptData((unsigned char*)"DemoData"); des.DescryptData(result);}运行结果实验二公钥密码加密解密实验实验学时:2学时实验类型:设计实验要求:必修【实验目的】1、掌握公钥密码体制的基本概念;2、掌握公钥密码体制加密/解密的工作原理;3、重点掌握RSA密码算法加密/解密的基本原理;4、通过用RSA算法对实际的数据进行加密/解密运算来深刻了解RSA的运行原理。