C语言实现DES算法实验报告
C语言DES加密算法.
云南大学软件学院School of Software, Y unnan University成绩学期: 2011秋季学期课程名称: 密码技术任课教师:学生姓名:学号:实验项目: 实验二 DES加密算法联系电话:电子邮件:完成提交时间:年月日密码技术实验报告实验项目:实验二,第2题实现DES对任意文件的加解密实验要求(内容)实现DES对任意文件的加解密,利用控制台对所有文件(中英文文本、符号甚至任意的文件)的加解密。
加解密形式如下:cipher -e/-d key inputfile outputfile说明:对于加密来说,输入文件名就是明文文件,对于解密来说,输入文件名就是密文文件,注意文件读取方式和控制文件结束控制台编程:int main(int argc, char *argv[ ])实验环境操作系统:win7编译环境:Microsoft Visual Studio 2010实现功能本次实验达到了题目的要求:实现了用DES实现控制台对任意文件的加解密,用键盘接收明文(密文)文件路径和密钥,然后再输入需要保存的密文(明文)文件路径,然后就可以把加解密后得到的密明文文件保存该路径下。
程序主要采取对数据的位操作的形式,把明密文文件中的内容以字节为单位读取,每次读取8个byte共65bits,然后使用标准DES的算法依次对读取的64bits明密文进出加解密处理。
主函数的操作也充分体现了程序的可操作性和健壮性,能够让用户自己选择相应的操作,比如加密、解密以及对程序的一些基本情况说明。
但是对文件的路径的输入有比较严格的格式约束。
如:盘符名:\\文件名.txt格式错误则会导致文件打开失败,不能进行加解密操作。
数据结构本次实验的程序较为复杂,涉及对位的操作。
实验过程中用到的主要数据结构为数组和文件型指针,在实验中我定义了2个文件型指针FILE *fp1,*fp2,其中一个指向明文文件,一个指向密文文件。
另外还定义了多个字符数组,如char Plainfpath[260]声明字符数组存储明文文件的文件路径,char Cipherfpath[260]声明字符数组存储密文文件的文件路径,char key[100]声明字符数组存储密钥。
关于DES加密算法的C语言实现
信息与网络安全实验报告计算机科学与技术学院网络工程1202班郭尚秀1208020204/********DES密码的加密过程*******************1.将字母转化为二进制数(明文&密文)分成两组完成*2.对明文m进行初始IP置换完成*3.对密钥k进行密钥置换完成*4.对密钥k进行压缩置换完成*5.对R0进行扩展变换32->48 完成*6.结果和k进行异或运算完成*7.将结果分成8组,通过8个s盒完成*8.对s盒的输出序列进行P置换完成*9.对p置换的结果与L0进行异或运算完成********************************************/#include<stdio.h>int ip[] = { //IP置换58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4,62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8,57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3,61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7};int jiou[] = {7,15,23,31,39,47,55,63 //进行密钥添加奇偶校验位使用};int ki[] = { //密钥置换57,49,41,33,25,17, 9, 1,58,50,42,34,26,18,10, 2,59,51,43,35,27,19,11, 3,60,52,44,36,63,55,47,39,31,23,15, 7,62,54,46,38,30,22,14, 6,61,53,45,37,29,21,13, 5,28,20,12, 4};int kyasuo[]= { //对密钥进行压缩置换14,17,11,24, 1, 5, 3,28,15, 6,21,10,23,19,12, 4,26, 8,16, 7,27,20,13, 2,41,52,31,37,47,55,30,40,51,45,33,48,44,49,39,56,34,53,46,42,50,36,29,32};int mkuozhan[]= {32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,8, 9,10,11,12,13,12,13,14,15,16,17,16,17,18,19,20,21,20,21,22,23,24,25,24,25,26,27,28,29,28,29,30,31,32, 1};int s[8][4][16] = { //8个s盒{{14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7},{ 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8},{ 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0},{15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13}},{{15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10},{ 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5},{ 0,14, 4,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15},{13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9}},{{10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8},{13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1},{13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7},{ 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12}},{{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15},{13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9},{10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4},{ 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14}},{{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9},{14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6},{10, 6, 9, 0,12,11, 7, 8,15, 9,12, 5, 6, 3, 0,14},{11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3}},{{12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11},{10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8},{ 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6},{ 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13}},{{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1},{13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6},{ 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2},{ 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12}},{{13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7},{ 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2},{ 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8},{ 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11}}};int p[32] = { //最后的p置换16, 7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10,2, 8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25};void main(){char mingwen1[100];int mingwen2[100];int tempmingwen[100];int L0[32],R0[32];int R48[48];char miyue1[100];int miyue2[100];int tempmiyue[100];int C0[28],D0[28];int yihuo[48]; //存放R0与K1异或的结果int sheD; //存放经过s盒之后的十进制结果int sheB[8][4]; //存放经过s盒之后的二进制结果int she[32]; //对s盒中的数据进行合并,存放经过s盒的结果int hang,lie; //存放s盒的行列序号int p2[32]; //存放经过p置换后的结果int c,d; //存放C0[0]和D0[0]int i,j; //i,j作为循环使用int icount1,icount2,k;int temp;//__________________________明文输入__________________________________________________________________________________ ________________k=0;printf("请输入明文(以'#'号结尾):\n");for(i=0; i<100; i++){scanf("%c",&mingwen1[i]);if('#' == mingwen1[i]){icount1 = i;goto loop1;}}loop1:for(i=0;i<=icount1;i++){for(j=7;j>=0;j--){temp=mingwen1[i]&(1<<j);if(0 == temp){mingwen2[k]=0;k++;}else{mingwen2[k]=1;k++;}}}//_________________________密钥输入__________________________________________________________________________________ _________________k=0;fflush(stdin); //清除缓冲区内的数据,如果不加上,则miwen[0]会多出一个LF(换行符)!!!printf("请输入密钥(以'#'号结束):\n");for(i=0; i<100; i++){scanf("%c",&miyue1[i]);if('#' == miyue1[i]){icount2 = i;goto loop2;}}loop2:for(i=0;i<=icount2;i++){for(j=7;j>=0;j--){temp=miyue1[i]&(1<<j);if(0 == temp){miyue2[k]=0;k++;}else{miyue2[k]=1;k++;}}}//**********************************************************printf("\n\nm = ");for(i=0;i<8*icount1;i++){printf("%d",mingwen2[i]);if(i== 7||i==15||i==23||i==39||i==47||i==55||i==63){printf(" ");}if(i==31){printf("\n");printf(" ");}}printf("\nk = ");for(i=0;i<8*icount2;i++){printf("%d",miyue2[i]);if(i== 7||i==15||i==23||i==39||i==47||i==55||i==63){printf(" ");}if(i==31){printf("\n");printf(" ");}}printf("\n");//**********************************************************///____________________至此二进制的明文存放在mingwen2[]中_____________________________________________________________________________//________________________进行明文的初始置换IP________________________________________________________________________________ _________________fflush(stdin); //清除缓冲区内的数据for(i=0;i<8*icount1;i++){tempmingwen[i] = mingwen2[ip[i]-1];}//________________________置换IP后的结果存放在tempmingwen[i]中__________________________________________________________________________//________________________把明文结果存放到L0和R0中__________________________________________________________________________________ ____fflush(stdin); //清除缓冲区内的数据for(i=0;i<64;i++){if(i<32) {L0[i]=tempmingwen[i];}else {R0[i-32]=tempmingwen[i];}}//**************************************printf("\nm经过IP置换后得到:\n");printf("L0: ");for(i=0;i<32;i++){printf("%d",L0[i]);if(i== 7||i==15||i==23||i==31){printf(" ");}}printf("\nR0: ");for(i=0;i<32;i++){printf("%d",R0[i]);if(i== 7||i==15||i==23||i==31){printf(" ");}}printf("\n");//**************************************///_______________________对密文进行添加奇偶校验位__________________________________________________________________________________ _____fflush(stdin); //清除缓冲区内的数据for(i=0;i<8;i++){j=56+i;while(j>=jiou[i]){miyue2[j+1]=miyue2[j];j--;}if(i==0 || i==2 || i==4 || i==6) {miyue2[jiou[i]]=0;}else {miyue2[jiou[i]]=1;}}/**********************************************************for(i=0;i<64;i++){printf("%d",miyue2[i]);if(i== 7||i==15||i==23||i==31||i==39||i==47||i==55||i==63){printf(" ");}}**********************************************************///_________________________对密文进行密钥置换__________________________________________________________________________________ _________________fflush(stdin); //清除缓冲区内的数据for(i=0;i<56;i++){tempmiyue[i]=miyue2[ki[i]-1];}/*********************************printf("\n\n");for(i=0;i<56;i++){printf("%d",tempmiyue[i]);if(i== 7||i==15||i==23||i==31||i==39||i==47||i==55||i==63){printf(" ");}}*********************************/fflush(stdin); //清除缓冲区内的数据for(i=0;i<56;i++){if(i<28) {C0[i]=tempmiyue[i];}else {D0[i-28]=tempmiyue[i];}}//**************************************printf("\n密钥k经过置换后得到:");printf("\nC0: ");for(i=0;i<28;i++)printf("%d",C0[i]);if(i== 7||i==15||i==23){printf(" ");}}printf("\nR0: ");for(i=0;i<28;i++){printf("%d",D0[i]);if(i== 7||i==15||i==23){printf(" ");}}printf("\n");//**************************************///_________________________分别对C0和D0进行循环左移操作__________________________________________________________________________________ __c = C0[0];d = D0[0];for(i=0;i<27;i++){C0[i] = C0[i+1];}C0[28] = c;for(i=0;i<27;i++){D0[i] = D0[i+1];}D0[28] = d;//__________________________对C0和D0进行合并存入miyue2[]中______________________________________________________________________________ fflush(stdin); //清除缓冲区内的数据for(i=0;i<56;i++){if(i<28) {miyue2[i]=C0[i];}else {miyue2[i]=D0[i-28];}}//_________________________________________________________________________________ _____-fflush(stdin); //清除缓冲区内的数据for(i=0;i<48;i++){tempmiyue[i] = miyue2[kyasuo[i]-1];}//**************************************printf("\n循环左移一位后经过密钥置换得到48位子密钥:\n");for(i=0;i<48;i++){printf("%d",tempmiyue[i]);if(i== 7||i==15||i==31||i==39||i==47){printf(" ");}if(i==23){printf("\n");}//**************************************/fflush(stdin); //清除缓冲区内的数据for(i=0;i<48;i++){R48[i]=R0[mkuozhan[i]-1];}//***************************************printf("\n\nR0经过扩展变换得到的48位序列为:\n");for(i=0;i<48;i++){printf("%d",R48[i]);if(i== 7||i==15||i==31||i==39||i==47){printf(" ");}if(i==23){printf("\n");}}//**************************************///______________________R0与K1异或______________________________________________________________fflush(stdin); //清除缓冲区内的数据for(i=0;i<48;i++){yihuo[i] = R48[i]^tempmiyue[i];}//______________________结果存放到yihuo[]数组中_________________________________________________//***************************************printf("\n\n结果再和k1进行异或运算,得到的结果为:\n");for(i=0;i<48;i++){printf("%d",yihuo[i]);if(i== 7||i==15||i==31||i==39||i==47){printf(" ");}if(i==23){printf("\n");}}//**************************************///_______________________通过8个s盒的到32位的序列_______________________________________________fflush(stdin); //清除缓冲区内的数据for(i=0;i<8;i++){k=0; //清除k的值hang=yihuo[(1+(i*6))-1]*2 + yihuo[(6+(i*6))-1];lie =yihuo[(2+(i*6))-1]*8 + yihuo[(3+(i*6))-1]*4 + yihuo[(4+(i*6))-1]*2 + yihuo[(5+(i*6))-1];sheD=s[i][hang][lie];for(j=3;j>=0;j--){temp=sheD&(1<<j);if(0 == temp){sheB[i][k]=0;k++;}else{sheB[i][k]=1;k++;}}}//______________________将二维数组sheB[][]中的内容转存到一维数组she中,方便以后的计算___________fflush(stdin); //清除缓冲区内的数据k=0;for(i=0;i<8;i++){for(j=0;j<4;j++){she[k]=sheB[i][j];k++;}}//*************************************printf("\n\n通过8个s盒得到32位的序列为:\n");for(i=0;i<32;i++){printf("%d",she[i]);if(i== 7||i==15||i==23||i==31){printf(" ");}}printf("\n");//*************************************///______________________对s盒的输出序列进行p置换__________________________________________________________fflush(stdin); //清除缓冲区内的数据for(i=0;i<32;i++){p2[i]=she[p[i]-1];}//*************************************fflush(stdin); //清除缓冲区内的数据printf("\n对s盒的输出序列进行p置换,得到\n");for(i=0;i<32;i++){printf("%d",p2[i]);if(i== 7||i==15||i==23||i==31){printf(" ");}}//*************************************///______________________p置换之后和L0进行异或运算_______________________________________________________________________________fflush(stdin); //清除缓冲区内的数据for(i=0;i<32;i++){p2[i]=L0[i]^p2[i];}//______________________L0和R0交换__________________________________________________________________________________ ______________________for(i=0;i<32;i++){L0[i]=R0[i];R0[i]=p2[i];}//*************************************printf("\n\n经过以上操作,得到进过第一轮加密的结果序列为:\n");printf("L0: ");for(i=0;i<32;i++){printf("%d",L0[i]);if(i== 7||i==15||i==23||i==31){printf(" ");}}printf("\n");printf("R0: ");for(i=0;i<32;i++){printf("%d",R0[i]);if(i== 7||i==15||i==23||i==31){printf(" ");}}printf("\n");}。
DES加密算法的C语言实现
试验名称:DES加密算法实现实验环境:VC++6.0试验原理:DES 使用一个56 位的密钥以及附加的8 位奇偶校验位,产生最大64 位的分组大小。
这是一个迭代的分组密码,使用称为Feistel 的技术,其中将加密的文本块分成两半。
使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。
DES 使用16 个循环,使用异或,置换,代换,移位操作四种基本运算。
算法流程设计:数据结构:#define PLAIN_FILE_OPEN_ERROR -1#define CIPHER_FILE_OPEN_ERROR -2#define OK 1//初始置换表IPint IP_Table[64] = { 57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7,56,48,40,32,24,16,8,0,58,50,42,34,26,18,10,2, 60,52,44,36,28,20,12,4, 62,54,46,38,30,22,14,6}; //逆初始置换表IP^-1int IP_1_Table[64] = {39,7,47,15,55,23,63,31,38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29,36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27,34,2,42,10,50,18,58,26,33,1,41,9,49,17,57,25,32,0,40,8,48,16,56,24};//扩充置换表Eint E_Table[48] = {31, 0, 1, 2, 3, 4,3, 4, 5, 6, 7, 8,7, 8,9,10,11,12,11,12,13,14,15,16,15,16,17,18,19,20,19,20,21,22,23,24,23,24,25,26,27,28,27,28,29,30,31, 0};//置换函数Pint P_Table[32] = {15,6,19,20,28,11,27,16,0,14,22,25,4,17,30,9,1,7,23,13,31,26,2,8,18,12,29,5,21,10,3,24};//S盒int S[8][4][16] =//S1{{{14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7},{0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8},{4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},{15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}},//S2{{15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},{3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5}, {0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15}, {13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9}}, //S3{{10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8}, {13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1}, {13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7}, {1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12}}, //S4{{7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15}, {13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9}, {10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4}, {3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14}}, //S5{{2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9}, {14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6}, {4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14}, {11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3}}, //S6{{12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11}, {10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8}, {9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6}, {4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13}}, //S7{{4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1}, {13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6}, {1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2}, {6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}}, //S8{{13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7}, {1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2}, {7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8}, {2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}}}; //置换选择1int PC_1[56] = {56,48,40,32,24,16,8,0,57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,60,52,44,36,28,20,12,4,27,19,11,3};//置换选择2int PC_2[48] = {13,16,10,23,0,4,2,27,14,5,20,9,22,18,11,3,25,7,15,6,26,19,12,1,40,51,30,36,46,54,29,39,50,44,32,46,43,48,38,55,33,52,45,41,49,35,28,31};//对左移次数的规定int MOVE_TIMES[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};部分代码://加密单个分组int DES_EncryptBlock(ElemType plainBlock[8], ElemType subKeys[16][48], ElemType cipherBlock[8]){ElemType plainBits[64];ElemType copyRight[48];int cnt;Char8ToBit64(plainBlock,plainBits);//初始置换(IP置换)DES_IP_Transform(plainBits);//16轮迭代for(cnt = 0; cnt < 16; cnt++){memcpy(copyRight,plainBits+32,32);//将右半部分进行扩展置换,从32位扩展到48位DES_E_Transform(copyRight);//将右半部分与子密钥进行异或操作DES_XOR(copyRight,subKeys[cnt],48);//异或结果进入S盒,输出32位结果DES_SBOX(copyRight);//P置换DES_P_Transform(copyRight);//将明文左半部分与右半部分进行异或DES_XOR(plainBits,copyRight,32);if(cnt != 15){//最终完成左右部的交换DES_Swap(plainBits,plainBits+32);}}//逆初始置换(IP^1置换)DES_IP_1_Transform(plainBits);Bit64ToChar8(plainBits,cipherBlock);return 0;}//解密单个分组int DES_DecryptBlock(ElemType cipherBlock[8], ElemType subKeys[16][48],ElemType plainBlock[8]){ElemType cipherBits[64];ElemType copyRight[48];int cnt;Char8ToBit64(cipherBlock,cipherBits);//初始置换(IP置换)DES_IP_Transform(cipherBits);//16轮迭代for(cnt = 15; cnt >= 0; cnt--){memcpy(copyRight,cipherBits+32,32);//将右半部分进行扩展置换,从32位扩展到48位DES_E_Transform(copyRight);//将右半部分与子密钥进行异或操作DES_XOR(copyRight,subKeys[cnt],48);//异或结果进入S盒,输出32位结果DES_SBOX(copyRight);//P置换DES_P_Transform(copyRight);//将明文左半部分与右半部分进行异或DES_XOR(cipherBits,copyRight,32);if(cnt != 0){//最终完成左右部的交换DES_Swap(cipherBits,cipherBits+32);}}//逆初始置换(IP^1置换)DES_IP_1_Transform(cipherBits);Bit64ToChar8(cipherBits,plainBlock);return 0;}//加密文件int DES_Encrypt(char *plainFile, char *keyStr,char *cipherFile){FILE *plain,*cipher;int count;ElemType plainBlock[8],cipherBlock[8],keyBlock[8];ElemType bKey[64];ElemType subKeys[16][48];if((plain = fopen(plainFile,"rb")) == NULL){return PLAIN_FILE_OPEN_ERROR;}if((cipher = fopen(cipherFile,"wb")) == NULL){return CIPHER_FILE_OPEN_ERROR;}//设置密钥memcpy(keyBlock,keyStr,8);//将密钥转换为二进制流Char8ToBit64(keyBlock,bKey);//生成子密钥DES_MakeSubKeys(bKey,subKeys);while(!feof(plain)){//每次读8个字节,并返回成功读取的字节数if((count = fread(plainBlock,sizeof(char),8,plain)) == 8){ DES_EncryptBlock(plainBlock,subKeys,cipherBlock);fwrite(cipherBlock,sizeof(char),8,cipher);}}if(count){//填充memset(plainBlock + count,'\0',7 - count);//最后一个字符保存包括最后一个字符在内的所填充的字符数量plainBlock[7] = 8 - count;DES_EncryptBlock(plainBlock,subKeys,cipherBlock);fwrite(cipherBlock,sizeof(char),8,cipher);}fclose(plain);fclose(cipher);return OK;}//解密文件int DES_Decrypt(char *cipherFile, char *keyStr,char *plainFile){ FILE *plain, *cipher;int count,times = 0;long fileLen;ElemType plainBlock[8],cipherBlock[8],keyBlock[8];ElemType bKey[64];ElemType subKeys[16][48];if((cipher = fopen(cipherFile,"rb")) == NULL){return CIPHER_FILE_OPEN_ERROR;}if((plain = fopen(plainFile,"wb")) == NULL){return PLAIN_FILE_OPEN_ERROR;}//设置密钥memcpy(keyBlock,keyStr,8);//将密钥转换为二进制流Char8ToBit64(keyBlock,bKey);//生成子密钥DES_MakeSubKeys(bKey,subKeys);//取文件长度fseek(cipher,0,SEEK_END); //将文件指针置尾fileLen = ftell(cipher); //取文件指针当前位置rewind(cipher); //将文件指针重指向文件头while(1){//密文的字节数一定是8的整数倍fread(cipherBlock,sizeof(char),8,cipher);DES_DecryptBlock(cipherBlock,subKeys,plainBlock); times += 8;if(times < fileLen){fwrite(plainBlock,sizeof(char),8,plain);}else{break;}}//判断末尾是否被填充if(plainBlock[7] < 8){for(count = 8 - plainBlock[7]; count < 7; count++){if(plainBlock[count] != '\0'){break;}}}if(count == 7){//有填充fwrite(plainBlock,sizeof(char),8 - plainBlock[7],plain);}else{//无填充fwrite(plainBlock,sizeof(char),8,plain);}fclose(plain);fclose(cipher);return OK;}试验结果:程序运行过程:。
【精品】DES算法实验报告
【精品】DES算法实验报告一、理论部分DES算法是一种对称加密算法,也是目前广泛应用的加密算法之一。
DES算法使用的是分组加密的思想,将明文数据分成一定长度的数据块,按照一定的算法进行加密,得到密文数据。
DES算法中的关键是密钥,只有持有正确密钥的人才能解密。
DES算法的密钥长度为64位,但由于存在弱密钥的问题,使用时需要特别注意。
DES算法的加密过程包括以下几个步骤:1、密钥的生成和处理:DES算法的密钥长度为64位,但由于存在弱密钥的问题,使用时需要使用程序进行特殊处理,以确保生成的密钥不为弱密钥。
2、初始置换(IP):将明文数据按照一定的规则进行置换,得到置换后的数据。
3、分组:将置换后的明文数据分成左半部分和右半部分。
4、轮函数(f函数):将右半部分进行扩展置换、异或运算、S盒代替、置换等操作,得到一个新的右半部分。
5、轮秘钥生成:生成本轮加密所需要的秘钥。
6、异或运算:将左半部分和右半部分进行异或运算,得到一个新的左半部分。
7、左右交换:将左右部分进行交换。
以上步骤循环执行16次,直到得到最终的密文数据。
二、实验部分本次实验使用C语言实现了DES算法的加密和解密过程。
具体实现过程包括以下几个部分:1、密钥的生成:使用DES算法生成64位密钥,其中包括了对弱密钥的处理。
2、置换:使用DES算法中的IP置换和IP逆置换进行数据置换。
3、轮函数:使用DES算法中的f函数进行一轮加密操作。
5、加密:循环执行16轮加密操作,得到密文数据。
以上实现过程全部基于DES算法的规范。
三、结果分析1、速度慢:由于DES算法采用的是分组加密的思想,需要执行多次操作才能得到最终结果。
因此本次实验的加密和解密速度相对较慢。
2、代码简单:本次实验的代码相对简单,只需要用到一些基本数据结构和算法即可实现DES算法的加密和解密过程。
但需要注意的是,由于DES算法本身的复杂性,代码实现中需要注意细节和边界问题。
四、总结本次实验使用C语言实现了DES算法的加密和解密过程,通过实验得到了一些结果。
DES密码算法综合实验报告
实
验
过
程
实验代码如下:
#include <iostream>
#include <fstream>
using namespace std;
FILE *file;
const static char rar[] = {
14, 17, 11, 24, 1, 5,
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
35, 3, 43, 11, 51, 19, 59, 27,
34, 2, 42, 10, 50, 18, 58, 26,
33, 1, 41, 9, 49, 17, 57, 25 };
bool key[16][48]={0},/*rekey[16][48],*/
char key_in[8];
void ByteToBit(bool *Out,char *In,int bits)
tmp[i*4+3]=sbox[i][(hang+1)*16+lie]%2;
tmp[i*4+2]=(sbox[i][(hang+1)*16+lie]/2)%2;
tmp[i*4+1]=(sbox[i][(hang+1)*16+lie]/4)%2;
tmp[i*4]=(sbox[i][(hang+1)*16+lie]/8)%2; }
DES实验报告
DES
[实验目的] C语言实现des加密解密
[实验原理]
1.DES的加密过程: 第一阶段:初始置换IP。在第一轮迭代之前,需要加密的64位明文首先通过初始置换IP 的作用,对输 入分组实施置换。最后,按照置换顺序,DES将64位的置换结果分为左右两部分,第1位到第32位记为 L0,第33位到第64位记为R0。 第二阶段:16次迭代变换。DES采用了典型的Feistel结构,是一个乘积结构的迭代密码算法。其算法的 核心是算法所规定的16次迭代变换。DES算法的16才迭代变换具有相同的结构,每一次迭代变换都以前 一次迭代变换的结果和用户密钥扩展得到的子密钥Ki作为输入;每一次迭代变换只变换了一半数据,它 们将输入数据的右半部分经过函数f后将其输出,与输入数据的左半部分进行异或运算,并将得到的结果 作为新的有半部分,原来的有半部分变成了新的左半部分。用下面的规则来表示这一过程(假设第i次迭 代所得到的结果为LiRi): Li = Ri-1; Ri = Li-1⊕ f(Ri-1,Ki);在最后一轮左与右半部分并未变换,而是直接 将R16 L16并在一起作为未置换的输入。 第三阶段:逆(初始)置换。 他是初始置换IP的逆置换,记为IP-1。在对16次迭代的结果(R16 L16) 再使用逆置换IP-1后,得到的结果即可作为DES加密的密文Y输出,即Y = IP-1 (R16 L16)。 2.DES解密过程: DES的解密算法与其加密算法使用的算法过程相同。两者的不同之处在于解密时子密钥Ki的使用顺序与 加密时相反,如果子密钥为K1K2… K16,那么解密时子密钥的使用顺序为K16K15… K1,即使用DES解密 算法进行解密时,将以64位密文作为输入,第1次迭代运算使用子密钥K16,第2次迭代运算使用子密钥 K15,… … ,第16 次迭代使用子密钥K1,其它的运算与加密算法相同。这样,最后输出的是64位明文。
des密码算法实验c语言
des密码算法实验c语言以下是一个使用C语言实现DES密码算法的简单实验示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <openssl/des.h>int main() {// 输入明文char plaintext[8] = "12345678";// 初始化DES密钥DES_cblock key = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};DES_key_schedule keysched;DES_set_key_unchecked(&key, &keysched);// 加密unsigned char ciphertext[8];DES_cblock ivec = {0}; // 初始化向量DES_ncbc_encrypt(plaintext, ciphertext, sizeof(plaintext),&keysched, &ivec, DES_ENCRYPT);// 输出密文printf("Ciphertext: ");for (int i = 0; i < sizeof(plaintext); i++) {printf("%02X", ciphertext[i]);}printf("\n");// 解密unsigned char decryptedtext[8];memset(ivec, 0, sizeof(ivec)); // 重置初始化向量DES_ncbc_encrypt(ciphertext, decryptedtext, sizeof(plaintext), &keysched, &ivec, DES_DECRYPT);// 输出明文printf("Plaintext: ");for (int i = 0; i < sizeof(plaintext); i++) {printf("%c", decryptedtext[i]);}printf("\n");return 0;}```在这个实验中,我们使用了OpenSSL库中的DES函数来实现DES 密码算法。
C语言实现DES算法实验报告
xx工程大学实验报告(2015-2016学年第一学期)报告题目: DES加密算法课程名称:密码学B任课教员:专业:学号:姓名:二O一六年一月十八日一、课程概述目的:培养学员的编程能力,理解算法原理。
要求:给出DES算法的软件实现,测试DES的加密速度。
二、设计思路使用C++语言进行编程,简化了输入输出语句。
预处理时加入了iostream包。
使用了std名字空间。
加密时程序输入的明文是8个ascii码,生成一个16个16进制数的密文。
脱密时程序输入的密文是16个16进制数,生成一个8个ascii码的明文。
加脱密所用密钥均由16个16进制数组成。
其中16进制数全部使用大写字母。
程序中大量使用了的布尔数组,一个bool型变量只占用一位存储空间,比int型、char型变量要小的多。
这降低了程序的空间复杂度。
三、采取的方案本程序是将一个由8个ascii码组成的明文分组加密,生成一个由16个16进制数组成的密文。
或将一个由16个16进制数组成的密文进行脱密,生成一个由8个ascii码组成的明文。
所用密钥由16个16进制数组成。
本实验按照输入数据及初始置换、16圈迭代、子密钥生成和逆初始置换及输出数据四个步骤实现加密算法设计。
1、输入数据及初始置换本程序首先会提示用户输入加密脱密识别码,加密输入1,脱密输入0,将此识别码存入整形变量o。
根据o的不同值,提示用户输入8个字符(加密)或16个16进制数(脱密)。
输入的明文或密文转化为二进制数后储存到布尔型数组m[65]中。
初始置换通过函数IP完成,函数输入为原始明文m,函数将输出结果保存到布尔型数组mip[65]中。
函数思想为查表,含有一个整形变量数组ip[64],保存初始变换表IP。
将mip的第i位赋值为m的第ip[i]位。
2、子密钥生成输入16个16进制数的密钥后,将密钥保存在一个16位字符数组c中,通过ToEr函数将之变为二进制数。
ToEr函数输入为字符数组,通过switch语句逐个检查字符数组的每一位,将对应的四位二进制数存在64位布尔数组k中。
DES_加密解密算法C实现--实验报告des算法实验
DES_加密解密算法C实现--实验报告des算法实验.....1实验一1、实验题目利用C/C++编程实现DES加密算法或MD5加密算法。
我选择的是用C++语言实现DES的加密算法。
2、实验目的通过编码实现DES算法或MD5算法,深入掌握算法的加密原理,理解其实际应用价值,同时要求用C/C++语言实现该算法,让我们从底层开始熟悉该算法的实现过程3、实验环境操作系统:WIN7旗舰版开发工具:VisualStudio2022旗舰版开发语言:C++4、实验原理DES加密流程2如上图所示为DES的加密流程,其中主要包含初始置换,压缩换位1,压缩换位2,扩展置换,S盒置换,异或运算、终结置换等过程。
初始置换是按照初始置换表将64位明文重新排列次序扩展置换是将原32为数据扩展为48位数据,它主要由三个目的:1、产生与子密钥相同的长度2、提供更长的结果,使其在加密过程中可以被压缩3、产生雪崩效应,使得输入的一位将影响两个替换S盒置换是DES算法中最核心的容,在DES中,只有S盒置换是非线性的,它比DES中其他任何一步都提供更好的平安性终结置换与初始置换相对应,它们都不影响DES的平安性,主要目的是为了更容易将明文与密文数据一字节大小放入DES的f算法中DES解密流程与加密流程根本相同,只不过在进行16轮迭代元算时,将子密钥生成的K的次序倒过来进行迭代运算5、实验过程记录在对DES算法有了清晰的认识后,编码过程中我将其分为几个关键局部分别进行编码,最后将整个过程按顺序执行,即可完成DES的加密,代码的主要几个函数如下://Byte转为BitByteToBit(ElemTypech,ElemTypebit[8])//Bit转为ByteBitToByte(ElemTypebit[8],ElemType&ch)//初始置换InitialE某(ElemTypeInorder[64],ElemTypeDisorder[64])//终结置换AntiE某(ElemTypeDisorder[64])//扩展置换E某pandE某(ElemTypeRightMsg[32],ElemTypeE某pandMsg[48])//16轮迭代加密MoveLeft(ElemTypeC[28],ElemTypeD[28],ElemTypeL0[32],ElemType R0[32])3//16轮迭代解密mMoveLeft(ElemTypeC[28],ElemTypeD[28],ElemTypeL0[32],ElemTyp eR0[32])//生成48位子密钥GetCD48(ElemTypeC[28],ElemTypeD[28],ElemTypeSecret[48])//48位明文与子密钥进行异或运算某OR(ElemTypeE某pandMsg[48],ElemTypeSecret[48],ElemTypeResult[48])//S盒四位输出getSOut(ElemTypeResult[48],ElemTypeSout[32])//直接置换DirE某change(ElemTypeSout[32],ElemTypeDirOut[32])//Li与Ri 进行抑或运算某ORLR(ElemTypeDirOut[32],ElemTypeLeft[32],ElemTypeResult[32])函数执行次序和调用关系关系如下:6.源代码//DES.cpp:定义控制台应用程序的入口点。
DES加密算法C语言 实验报告
DES实验报告一、实验目的实现DES算法。
二、实验过程按照DES的算法流程设计,具体实施详见附件。
三、使用方法首先输入密钥,八位ASCII长,否则报错。
然后输入读入文件名和写入文件名,必须以ASCII编码,否则不能使用。
四、实验结果将自身cpp文件进行加密解密,前后文件完全一样。
见文件附录源代码:// 滴一欸死.cpp : 定义控制台应用程序的入口点。
//#include"stdafx.h"#include<stdio.h>#include<stdlib.h>#include<string.h>#include<malloc.h>#include<conio.h>#include"table.h"/* Constant */#define ENCRYPT_LENGTH8 //length of each unit in encryption#define DECIPHER_LENGTH 4 //length of each unit in decipher#define MAX320xFFFFFFFF //mask of 32 bits/* Declaration */typedefunsignedlonglong bit64;typedefunsignedlonglong bit56;typedefunsignedlonglong bit48;typedefunsignedint bit32;typedefunsignedint bit28;/* File stream */FILE *fin, *fout;/* For debug */inlinevoid printBite(bit64num){while (num){printf("%d", num % 2);num>>= 1;}printf("\n");}/* Transfer from char to bit in Encrtption */ inline bit64 ToBit(char *in // source string);/* Transfer from char to bit in Deciphtering */ inline bit64 DeToBit(char *in // source string);/* Transfer from bit to char */inlinevoid ToBite(char *out, // out stringbit64 num // source bits);/* Permutation */inline bit64 substitute(bit64 num, // source bitsconstint *table, // Permutation tablesize_t len // bits length);/* Bit recycle loop to left */inline bit28 MoveLeft(bit28 key, // source bitsint len // bits length);/* Bit recycle loop to right */inline bit28 MoveRight(bit28 key, // source bitsint len // bits length);/* Divide bits into two parts */inlinevoid divide(bit64 num, // source bitsint len, // length of each bitsbit32 *L, // left out bitsbit32 *R // right out bits);/* S box */inline bit32 SChange(bit48 num // source bits);/* F box */inline bit32 FChange(bit32 num, // source bitsbit48 key // secret key);/* Key initialization */inlinevoid SetKey(char *in // string of key);/* Enryption */inlinevoid DES(char *message // messages to be encrypted);/* Deciphering */inlinevoid Decipher(char *message // messages to be deciphered );/* Initialization */inlinevoid init();int main(){init();system("pause");return 0;}/* Initialization */inlinevoid init(){/* Set secret key */printf("Please input your secret key (8 digits):\n");char key[10000];scanf("%s", key);if (strlen(key) != 8){printf("ERROR Key\n");return;}SetKey(key);/* Set mode Encryption or Deciphering */printf("Please input the mode (\"E\" for Encrypt, \"D\" for Decipher):\n");void (*p)(char*);int delta = 8;switch (getch()){case'E': p = DES; delta = 8; break;case'D': p = Decipher; delta = 16; break;default: printf("ERROR!\n"); return;}/* Load file */printf("Please input the path of the in file:\n");char message[10000], in[100], out[100];scanf("%s", in);printf("Please input the path of the out file:\n");scanf("%s", out);fin = freopen(in, "r", stdin);fout = freopen(out, "w", stdout);/* If success */if (!fin || !fout){printf("Error open file!\n");return;}/* Read file */while (gets_s(message)){for (int i = 0; i < strlen(message); i += delta){p(message + i);}printf("\n");}/* Close stream */fclose(stdin);fclose(stdout);fclose(fin);fclose(fout);}/* Transfer from char to bit in Encrtption */inline bit64 ToBit(char *in){/* If valid */if (!in){return 0;}/* Copy char* */char temp[8];memset(temp, ' ', 8 * sizeof(char));for (int i = 0; i < strlen(in) && i <ENCRYPT_LENGTH; i++) {temp[i] = in[i];}/* Transfer to bit */bit64 key = 0x0;for (int i = 0; i <ENCRYPT_LENGTH; i++){key |= ((bit64)temp[i] << (ENCRYPT_LENGTH * i));}return key;}/* Transfer from char to bit in Deciphtering */inline bit64 DeToBit(char *in){/* If valid */if (!in){return 0;}/* Copy char* */char temp[64 / DECIPHER_LENGTH];memset(temp, ' ', 8 * sizeof(char));for (int i = 0; i < 64 / DECIPHER_LENGTH; i++){if (in[i] >= 'A'){temp[i] = in[i] - '7';}else{if (in[i] >= '0'){temp[i] = in[i] - '0';}}}/* Transfer to bit */bit64 key = 0x0;for (int i = 0; i < 64 / DECIPHER_LENGTH; i++){key |= ((bit64)temp[i] << (DECIPHER_LENGTH * i));}return key;}/* Transfer from bit to char */inlinevoid ToBite(char *out, bit64num){if (strlen(out) <= ENCRYPT_LENGTH){out = (char*)malloc(sizeof(char) * (ENCRYPT_LENGTH + 1));}memset(out, 0, sizeof(char) * (ENCRYPT_LENGTH + 1));for (int i = 0; i <ENCRYPT_LENGTH; i++){out[i] = num& 0xFF;}}/* Permutation */inline bit64 substitute(bit64num, constint *table, size_t len) {bit64 out = 0;/* Calculation */for (int i = 0; i <len; i++){out |= ((bit64)((num>> (table[i] - 1)) & 1) << i);}return out;}/* Bit recycle loop to left */inline bit28 MoveLeft(bit28key, int len){bit28 temp = 0;temp = key<< (28 - len); // right bitskey = key>>len; // left bitskey |= temp; // comparekey&= 0x0FFFFFFF; // delete highest four bits return key;}/* Bit recycle loop to right */inline bit28 MoveRight(bit28key, int len){bit28 temp = 0;temp = key>> (28 - len); // right bitskey = key<<len; // left bitskey |= temp; // comparereturn key;}/* Divide bits into two parts */inlinevoid divide(bit64num, int len, bit32 *L, bit32 *R){*L = *R = 0;*L = num&MAX32;*R = num&MAX32;}/* S box */inline bit32 SChange(bit48num){bit32 key = 0;for (int i = 0; i < 8; i++){bit32 x, y;x = (num>> 1) & 0x0F; // the middle four bitsy = (((num>> 5) & 1) << 1) | (num& 1); // the first and the last bitskey |= (S[i][y][x] << (i * 4)); // permutatenum>>= 6; // change to next }return key;}/* F box */inline bit32 FChange(bit32num, bit48key){bit48 temp = substitute(num, E, sizeof(E) / sizeof(E[0]));temp ^= key;num = SChange(temp);return substitute(num, P, sizeof(P) / sizeof(P[0]));}/* Key initialization */inlinevoid SetKey(char *in){bit64 key = ToBit(in);bit28 C, D;key = substitute(key, PC1, sizeof(PC1) / sizeof(PC1[0]));divide(key, 28, &C, &D);for (int i = 0; i < 16; i++){C = MoveLeft(C, Move[i]);D = MoveLeft(D, Move[i]);key = (bit64)C | ((bit64)D << 28);SubKey[i] = substitute(key, PC2, 48);}}/* Enryption */inlinevoid DES(char *message){bit64 BitMes = substitute(ToBit(message), IP, sizeof(IP) / sizeof(IP[0]));bit32 L, R, temp;divide(BitMes, 32, &L, &R);/* 16 rounds */for (int i = 0; i < 16; i++){temp = R;R = FChange(R, SubKey[i]);R ^= L;L = temp;}BitMes = (bit64)L | ((bit64)R << 32);BitMes = substitute(BitMes, IPR, sizeof(IPR) / sizeof(IPR[0]));/* print encrypted message */for (int i = 0; i < 16; i++){char temp = (0xF & (BitMes >> (i * 4)));temp += (temp > 9 ? '7' : '0');printf("%c", temp);}}/* Deciphering */inlinevoid Decipher(char *message){bit64 BitMes = substitute(DeToBit(message), IP, sizeof(IP) / sizeof(IP[0]));bit32 L, R, temp;divide(BitMes, 32, &L, &R);/* 16 rounds */for (int i = 15; i >= 0; i--){temp = L;L = FChange(L, SubKey[i]);L ^= R;R = temp;}BitMes = (bit64)L | ((bit64)R << 32);BitMes = substitute(BitMes, IPR, sizeof(IPR) / sizeof(IPR[0]));/* print deciphered messages */for (int i = 0; i < 8; i++){printf("%c", (0xFF & (BitMes >> (i * 8))));}}table.h文件#pragmaonce/* IP permutation for plaintext */constint IP[64] = {58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4,62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8,57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3,61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7};/* IPR permutation to print */constint IPR[64] = {40, 8,48,16,56,24,64,32,39, 7,47,15,55,23,63,31,38, 6,46,14,54,22,62,30,37, 5,45,13,53,21,61,29,36, 4,44,12,52,20,60,28,35, 3,43,11,51,19,59,27,34, 2,42,10,50,18,58,26,33, 1,41, 9,49,17,57,25};/*--------------------------- premutation ----------------------------*//* the expansion permutation */staticint E[48] = {32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9,8, 9,10,11,12,13,12,13,14,15,16,17,16,17,18,19,20,21,20,21,22,23,24,25,24,25,26,27,28,29,28,29,30,31,32, 1};/* Compression permutation */staticint PC1[56] = {57,49,41,33,25,17, 9, 1,58,50,42,34,26,18,10, 2,59,51,43,35,27,19,11, 3,60,52,44,36,63,55,47,39,31,23,15, 7,62,54,46,38,30,22,14, 6,61,53,45,37,29,21,13, 5,28,20,12, 4};/* Number of key bits shifted per round */staticint Move[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };/* Compression permutation */staticint PC2[48] = {14,17,11,24, 1, 5, 3,28,15, 6,21,10,23,19,12, 4,26, 8,16, 7,27,20,13, 2,41,52,31,37,47,55,30,40,51,34,33,48,44,49,39,56,34,53,46,42,50,36,29,32};/*------------- F function ---------------*//* S boxes permutation */staticint S[8][4][16] = {//S114, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7, 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8, 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0, 15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13, //S215, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10, 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5, 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15, 13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9, //S310, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8, 13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1, 13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7, 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12, //S47,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15, 13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9, 10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4, 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14,//S52,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9, 14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6, 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14, 11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3, //S612, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11, 10,15, 4, 2, 7,12, 0, 5, 6, 1,13,14, 0,11, 3, 8, 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6, 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13, //S74,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1, 13, 0,11, 7, 4, 0, 1,10,14, 3, 5,12, 2,15, 8, 6, 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2, 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12, //S813, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7, 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2, 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8, 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11 };/* P boxes permutation */staticint P[32] = {16, 7,20,21,29,12,28,17, 1,15,23,26, 5,18,31,10, 2, 8,24,14,32,27, 3, 9,19,13,30, 6,22,11, 4,25 };/* 16 subkey undefined */staticunsignedlonglong SubKey[16];。
实验报告 DES加密算法的实现
实验报告DES加密算法的实现班级自动化学号:姓名:2016年11月13日星期日一、DES加密简述:DES算法是一种对称密码体制,由美国IBM公司在1972年研发。
其明文按64位进行分组,密钥长64位(包含8位校验位),分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法。
二、DES的实现过程首先通过初始置换表IP对明文进行置换intIP_Table[64] = { 57,49,41,33,25,17,9,1,59,51,43,35,27,19,11,3,61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,7,56,48,40,32,24,16,8,0,58,50,42,34,26,18,10,2,60,52,44,36,28,20,12,4,62,54,46,38,30,22,14,6};第一个57就是将明文中的第57个元素,放到第1的位置,然后把明文中第49个元素放到第2的位置,以此类推。
之后将换位后的输出分为两部分L0和R0,L0是输出的左32位,R0 是右32位。
intDES_IP_Transform(char data[64]){intcnt;char temp[64];for(cnt = 0; cnt< 64; cnt++){temp[cnt] = data[IP_Table[cnt]];}memcpy(data,temp,64);return 0;}之后加密函数,将R0通过位选择函数E置换,把本身是32位的R0扩充成48位,与生成的48位子密钥对应,按位运算。
intE_Table[48] = {31, 0, 1, 2, 3, 4,3, 4, 5, 6, 7, 8,7, 8,9,10,11,12,11,12,13,14,15,16,15,16,17,18,19,20,19,20,21,22,23,24,23,24,25,26,27,28,27,28,29,30,31, 0};intDES_E_Transform(char data[48]){intcnt;char temp[48];for(cnt = 0; cnt< 48; cnt++){temp[cnt] = data[E_Table[cnt]];}memcpy(data,temp,48);return 0;}然后,将扩充完的R0和子密钥K1进行模2加运算,得到48位的一个串,把这个串从左到右分为8组,每组6个字符。
des算法实验报告
《计算机安全技术》实验报告一、实验内容:des加密解密算法实现二、实验环境:1、操作系统:Windows XP及以上2、编程工具:Visual C++ 6.0三、实验原理:DES算法为密码体制中的对称密码体制,又被成为美国数据加密标准,是1972年美国IBM公司研制的对称密码体制加密算法。
明文按64位进行分组, 密钥长64位,密钥事实上是56位参与DES运算(第8、16、24、32、40、48、56、64位是校验位,使得每个密钥都有奇数个1)分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法。
基本原理:其入口参数有三个:key、data、mode。
key为加密解密使用的密钥,data为加密解密的数据,mode为其工作模式。
当模式为加密模式时,明文按照64位进行分组,形成明文组,key用于对数据加密,当模式为解密模式时,key用于对数据解密。
实际运用中,密钥只用到了64位中的56位,这样才具有高的安全性。
算法特点:分组比较短、密钥太短、密码生命周期短、运算速度较慢。
四、算法流程设计:1、DES算法整体结构:2、16轮迭代:3、子密钥产生:4、f函数:五、算法实现:1、部分函数定义:static void F_func(bool In[], const bool Ki[]);// F 函数static void S_func(bool Out[], const bool In[]);// S 盒代替static void Transform(bool *Out, bool *In, const char *Table, int len);// 变换static void Xor(bool *InA, const bool *InB, int len);// 异或static void RotateL(bool *In, int len, int loop);// 循环左移static void ByteToBit(bool *Out, const char *In, int bits);// 字节组转换成位组static void BitToByte(char *Out, const bool *In, int bits);// 位组转换成字节组static void BitToHex(char *Out,const bool *In, int bits);// 将二进制转换为十六进制2、主要功能模块:void Des_SetKey(const char Key[]){ //生成子密钥static bool K[64], *KL = &K[0], *KR = &K[28];ByteToBit(K, Key, 64);for(int i=0; i<16; i++){RotateL(KL, 28, LOOP_Table[i]); //循环左移RotateL(KR, 28, LOOP_Table[i]);Transform(SubKey[i], K, PC2_Table, 48); //PC2变换}}void Des_Run(char Out1[],char Out2[], char In[], bool Type){ //des加密解密过程static bool M[64], Tmp[32], *Li = &M[0], *Ri = &M[32];ByteToBit(M, In, 64);Transform(M, M, IP_Table, 64); //IP置换if( Type == ENCRYPT ){ //加密for(int i=0; i<16; i++) {memcpy(Tmp, Ri, 32);F_func(Ri, SubKey[i]); //F函数Xor(Ri, Li, 32); //异或memcpy(Li, Tmp, 32);}}else{ //解密for(int i=15; i>=0; i--) {memcpy(Tmp, Li, 32);F_func(Li, SubKey[i]); //F函数Xor(Li, Ri, 32); //异或memcpy(Ri, Tmp, 32);}}Transform(M, M, IPR_Table, 64); //IP-1置换BitToByte(Out1, M, 64); //Out1为字符形式密文 BitToHex(Out2, M, 64); //Out2为十六进制数形式密文}void F_func(bool In[], const bool Ki[]){ //F函数static bool MR[48];Transform(MR, In, E_Table, 48); //E扩展Xor(MR, Ki, 48); //异或密钥S_func(In, MR); //S盒代换Transform(In, In, P_Table, 32); //P置换}3、调试中遇到的问题及解决办法问题:通过BitToByte()函数转换只能看到字符形式的密文,为乱码。
DES实验报告
DES实验报告DES加解密算法实现⼀、实验⽬的在这⼀实验中,⽤VC++实现DES加解密算法。
完成实验后,将能够深⼊理解DES加解密算法及其在VC++中的实现过程。
⼆、实验条件熟悉VC++开发环境和有关DES算法知识,安装了VC++6.0系统的计算机。
三、任务描述对数据进⾏加密传输能有效地保证数据的机密性,DES算法是⼀个保护数据的机密性的经典算法,本实验在VC++环境中实现DES算法。
在VC++中建⽴⼀个项⽬,并将资料盘中的DES程序代码添⼊项⽬中,实现加/解密功能。
四、操作步骤1.进⼊Microsoft Vilual C++ 6.0系统界⾯,选择菜单中的File--New,出现New 对话框。
2.在对话框中,选择Projects页,在左侧的列表中选择MFC AppWizard[exe],在Project name⽂本框中输⼊新建项⽬的名称,如DES加解密算法,在Location ⽂本框中选择项⽬存储路径。
单击OK按钮出现MFC AppWizard-step1对话框。
3.在对话框中,选择Dialog based,单击Next按钮。
4.之后出现的对话框MFC AppWizard-step 2 of 4、MFC AppWizard-step 3 of 4中均单击Next按钮。
MFC AppWizard-step 4 of 4中单击Finish,出现New Project Information对话框。
单击OK按钮,⼀个新项⽬就建成了。
5. 在对话框上添加控件资源,如图1所⽰。
6.在VC++菜单中选择View中ClassWizard命令,为控件资源定义变量,出现对话框。
可以看到类的所有可被定义变量的控件资源,为每个资源分别定义变量。
如:在列表中选择IDC_EDIT1,然后单击Add Variable按钮,在其后出现的对话框中输⼊变量名即可。
图1 DES加密解密对话框7.添加其他变量,右击CDESDlg在弹出的菜单中选择Add Member Variable…命令,在新出现的对话框中,输⼊变量类型、变量名,选择变量的访问类型。
des算法的实验报告
des算法的实验报告DES算法实验报告DES(Data Encryption Standard)算法是一种对称密钥加密算法,广泛应用于信息安全领域。
本实验旨在通过实验DES算法的加密和解密过程,以及密钥长度对加密效果的影响,来深入了解DES算法的原理和应用。
实验一:加密和解密过程首先,我们使用一个明文进行加密实验。
选择一个64位的明文作为输入,同时使用一个64位的密钥进行加密。
经过DES算法加密后,得到的密文长度也为64位。
然后,我们使用相同的密钥对密文进行解密,得到原始的明文。
实验结果表明,DES算法能够对明文进行有效的加密,并且使用相同的密钥能够对密文进行解密,得到原始的明文。
这说明DES算法是一种可靠的加密算法,能够保护数据的安全性。
实验二:密钥长度对加密效果的影响在第二个实验中,我们对不同长度的密钥进行加密实验,观察加密效果的变化。
我们分别使用56位、64位和128位的密钥进行加密,然后比较不同长度密钥的加密效果。
实验结果显示,密钥长度对加密效果有显著影响。
使用128位的密钥进行加密,能够得到更加安全的密文,而使用56位的密钥进行加密,则容易受到攻击。
这表明密钥长度是影响DES算法加密效果的重要因素。
结论通过本实验,我们深入了解了DES算法的加密和解密过程,以及密钥长度对加密效果的影响。
DES算法是一种可靠的加密算法,能够有效保护数据的安全性。
同时,密钥长度对加密效果有显著影响,因此在实际应用中需要选择足够长度的密钥来保障数据的安全。
总之,DES算法在信息安全领域有着重要的应用价值,通过本实验的学习,我们对DES算法有了更深入的了解,为进一步研究和应用提供了重要的参考。
DES 加密解密算法的C完成 实验报告
美国国家标准局 1973 年开始研究除国防部外的其它部门的计算机系统的数据加密标准, 于 1973 年 5 月 15 日和 1974 年 8 月 27 日先后两次向公众发出了征求加密算法的公告。加 密算法要达到的目的通常称为 DES 密码算法要求主要为以下四点:
DES 算法的入口参数有三个:Key、Data、Mode。其中 Key 为 8 个字节共 64 位,是 DES 算法的工作密钥;Data 也为 8 个字节 64 位,是要被加密或被解密的数据;Mode 为 DES 的工作方式,有两种:加密或解密。
DES 算法是这样工作的:如 Mode 为加密,则用 Key 去把数据 Data 进行加密, 生成 Data 的密码形式(64 位)作为 DES 的输出结果;如 Mode 为解密,则用 Key 去把密码形 式的数据 Data 解密,还原为 Data 的明码形式(64 位)作为 DES 的输出结果。在通信网络 的两端,双方约定一致的 Key,在通信的源点用 Key 对核心数据进行 DES 加密,然后以密 码形式在公共通信网(如电话网)中传输到通信网络的终点,数据到达目的地后,用同样 的 Key 对密码数据进行解密,便再现了明码形式的核心数据。这样,便保证了核心数据 (如 PIN、MAC 等)在公共通信网中传输的安全性和可靠性。
目前在这里,随着三金工程尤其是金卡工程的启动,DES 算法在 POS、ATM、磁卡及 智能卡(IC 卡)、加油站、高速公路收费站等领域被广泛应用,以此来实现关键数据的保 密,如信用卡持卡人的 PIN 的加密传输,IC 卡与 POS 间的双向认证、金融交易数据包的 MAC 校验等,均用到 DES 算法。
计算机网络安全--对称密码算法DES实验报告
实验一对称密码算法DES一、实验目的通过用DES算法对实际的数据进行加密和解密来深刻了解DES的运行原理。
二、实验环境运行Windows或Linux操作系统的PC机,具有gcc(Linux)、VC(Windows)等C语言编译环境。
三、实验内容和步骤(1)使用附录提供的程序对一个文件进行加密和解密,程序代码和执行结果如下所示。
程序代码:#include "des.h"#include "stdio.h"int main(int argc, char *argv[]){unsigned char key[8]= { 'a','b','c','d','a','b','c','d' };des_key skey;des_setup(key,8,0,&skey);FILE *fd1;FILE *fd2;fd1=fopen("plaintext1.txt","rb");fd2=fopen("cipertext.txt","wb");int count=0;unsigned char p_buf[8];unsigned char c_buf[8];while(true){count=fread(p_buf,sizeof(unsigned char),8,fd1);if(count<8)for(int i=count;i<=7;i++)p_buf[i]='\0';des_ecb_encrypt(p_buf,c_buf,&skey);fwrite(c_buf,sizeof(unsigned char),8,fd2);if(count<8)break;count=0;}fclose(fd1);fclose(fd2);fd2=fopen("cipertext.txt","rb");网络安全实验报告学院专业班学号姓名成绩评定_______ 教师签名实验 1 题目对称密码算法DES 课程名称网络安全fd3=fopen("plaintext2.txt","wb");while(true){count=fread(p_buf,sizeof(unsigned char),8,fd2);if(count==0)break;des_ecb_decrypt(p_buf,c_buf,&skey);fwrite(c_buf,sizeof(unsigned char),8,fd3);count=0;}fclose(fd2);fclose(fd3);system("PAUSE");return 0;}程序执行结果:例如plaintext1.txt存放的明文为:加密后的密文为:解密后plaintext2.txt中的明文为:(2)使用附录提供的程序对输入的十六进制数加密(把输入的字符转化成整数。
DES算法实验报告
实验报告:xxxx学号:0XXXXX 班级:XXXXXXX日期:2013/11/*题目:DES算法实验一、实验环境1.硬件配置:处理器:Inter(R) Core(TM) i5-2430M CPU 2.40GHz (4 CPUs) ,~2.4GHz存:2048MB RAM2.使用软件:(1) 操作系统:win7 旗舰版(2) 软件工具:Microsoft Visual c++ 6.0二、实验涉及的相关概念或基本原理DES是一个分组密码算法,使用64位密钥(除去8位奇偶校验,实际密钥长度为56位)对64比特的数据分组(二进制数据)加密,产生64位密文数据。
DES是一个对称密码体制,加密和解密使用同意密钥,解密和加密使用同一算法(这样,在硬件与软件设计时有利于加密单元的重用)。
DES的所有的性均依赖于密钥。
DES的加密过程可分为加密处理,加密变换和子密钥生成几个部分组成。
1.加密处理过程(1)初始置换IP。
加密处理首先要对64位的明文按表1所示的初始换位表IP进行变换。
表中的数值表示输入位被置换后的新位置。
(2)加密处理。
上述换位处理的输出,中间要经过16轮加密变换。
初始置换的64位的输出作为下一次的输入,将64位分为左、右两个32位,分别记为L0和R,从L、R到L16、R16,共进行16轮加密变换。
其中,经过i轮处理后的点左右32位分别为Li 和Ri则可做如下定义:L i =Ri-1R i =Li-1⊕F(Ri-1,K) 其中,F为F变换(3)最后换位。
进行16轮的加密变换之后,将L16和R16合成64位的数据,再按照表2所示的最后换位表进行IP-1的换位,得到64位的密文,这就是DES算法加密的结果。
2.加密变换过程64位的密钥先由置换选择1减少至56六位,进行循环左移,然后通过置换选择2减少至48位。
而通过扩展运算将32位按表3扩展换位表扩展为48位的右半部分通过异或操作和48位的密钥结合,并分成6位的8个分组,通过8个S-盒将这48位替代成新的32位数据。
C语言实现DES算法实验报告
xx工程大学实验报告(2015-2016学年第一学期)报告题目:DES加密算法课程名称:密码学B任课教员:专业:学号:姓名:二O一六年一月十八日一、课程概述目的:培养学员的编程能力,理解算法原理。
要求:给出DES算法的软件实现,测试DES的加密速度。
二、设计思路使用C++语言进行编程,简化了输入输出语句。
预处理时加入了iostream包。
使用了std名字空间。
加密时程序输入的明文是8个ascii码,生成一个16个16进制数的密文。
脱密时程序输入的密文是16个16进制数,生成一个8个ascii码的明文。
加脱密所用密钥均由16个16进制数组成。
其中16进制数全部使用大写字母。
程序中大量使用了的布尔数组,一个bool型变量只占用一位存储空间,比int型、char型变量要小的多。
这降低了程序的空间复杂度。
三、采取的方案本程序是将一个由8个ascii码组成的明文分组加密,生成一个由16个16进制数组成的密文。
或将一个由16个16进制数组成的密文进行脱密,生成一个由8个ascii 码组成的明文。
所用密钥由16个16进制数组成。
本实验按照输入数据及初始置换、16圈迭代、子密钥生成和逆初始置换及输出数据四个步骤实现加密算法设计。
1、输入数据及初始置换本程序首先会提示用户输入加密脱密识别码,加密输入1,脱密输入0,将此识别码存入整形变量o。
根据o的不同值,提示用户输入8个字符(加密)或16个16进制数(脱密)。
输入的明文或密文转化为二进制数后储存到布尔型数组m[65]中。
初始置换通过函数IP 完成,函数输入为原始明文m ,函数将输出结果保存到布尔型数组mip[65]中。
函数思想为查表,含有一个整形变量数组ip[64],保存初始变换表IP 。
将mip 的第i 位赋值为m 的第ip[i]位。
2、子密钥生成输入16个16进制数的密钥后,将密钥保存在一个16位字符数组c 中,通过ToEr 函数将之变为二进制数。
ToEr 函数输入为字符数组,通过switch 语句逐个检查字符数组的每一位,将对应的四位二进制数存在64位布尔数组k 中。
密码学 DES C语言
数学与软件科学学院实验报告学期:_2011_至_2012_ 第__2 学期 2012 年月日课程名称: _ 专业:信息与计算科学 _2009_级_06_班实验编号:实验项目_ 指导教师_ _姓名:林海学号: 2009060619 实验成绩:___实验1-2 对称密码算法DES一.实验原理信息加密根据采用的密钥类型可以划分为对称密码算法和非对称密码算法。
对称密码算法是指加密系统的加密密钥和解密密钥相同,或者虽然不同,但是可以从其中任意一个推导出另一个,更形象的说就是用同一把钥匙开锁和解锁。
在对称密码算法的发展历史中曾出现过多种优秀的算法,包括DES、3DES、AES等。
下面我们以DES算法为例介绍对称密码算法的实现机制。
DES算法是有美国IBM公司在20世纪70年代提出,并被美国政府、美国国家标准局和美国国家标准协会采纳和承认的一种标准加密算法。
它属于分组加密算法,即明文加密和密文解密过程中,信息都是按照固定长度分组后进行处理的。
混淆和扩散是它采用的两个最重要的安全特性,混淆是指通过密码算法使明文和密文以及密钥的关系非常复杂,无法从数学上描述或者统计。
扩散是指明文和密钥中每一位信息的变动,都会影响到密文中许多位信息的变动,从而隐藏统计上的特性,增加密码安全。
DES将明文分成64比特位大小的众多数据块,即分组长度为64位。
同时用56位密钥对64位明文信息加密,最终形成64位的密文。
如果明文长度不足64位,则将其扩展为64位(例如补零等方法)。
具体加密过程首先是将输入的数据进行初始换位(IP),即将明文M中数据的排列顺序按一定的规则重新排列,生成新的数据序列,以打乱原来的次序。
然后将变换后的数据平分成左右两部分,左边记为L0,右边记为R0,然后对R0施行在子密钥(由加密密钥产生)控制下的变换f,结果记为f(R0 ,K1),再与L0做逐位异或运算,其结果记为R1,R0则作为下一轮的L1。
如此循环16轮,最后得到L16、R16,再对L16、R16施行逆初始置换IP-1,即可得到加密数据。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
XX工程大学实验报告(2015-2016学年第一学期)报告题目:DES 加密算法______________ 课程名称: _____________ 密码学B ________________ 任课教员: _______________________________________ 专业: __________________________________________ 学号: __________________________________________ 姓名: __________________________________________O一六年一月十八日'、课程概述目的:培养学员的编程能力,理解算法原理要求:给出DES算法的软件实现,测试DES勺加密速度。
二、设计思路使用C++语言进行编程,简化了输入输出语句。
预处理时加入了iostream包。
使用了std 名字空间。
加密时程序输入的明文是8个ascii码,生成一个16个16进制数的密文。
脱密时程序输入的密文是16个16进制数,生成一个8个ascii码的明文。
加脱密所用密钥均由16个16进制数组成。
其中16进制数全部使用大写字母。
程序中大量使用了的布尔数组,一个bool型变量只占用一位存储空间,比int型、char 型变量要小的多。
这降低了程序的空间复杂度。
三、采取的方案本程序是将一个由8个ascii码组成的明文分组加密,生成一个由16个16进制数组成的密文。
或将一个由16个16进制数组成的密文进行脱密,生成一个由 8个ascii 码组成的明文。
所用密钥由16个16进制数组成。
本实验按照输入数据及初始置换、16圈迭代、子密钥生成和逆初始置换及输出数据四个步骤实现加密算法设计。
1、输入数据及初始置换本程序首先会提示用户输入加密脱密识别码,加密输入 1,脱密输入0,将此识别码存入整形变量0。
根据o的不同值,提示用户输入8个字符(加密)或16个16进制数(脱密)。
输入的明文或密文转化为二进制数后储存到布尔型数组 m[65]中。
初始置换通过函数IP完成,函数输入为原始明文 m函数将输出结果保存到布尔型数组mip[65]中。
函数思想为查表,含有一个整形变量数组ip[64],保存初始变换表IP。
将mip 的第i位赋值为m的第ip[i]位。
2、 子密钥生成输入16个16进制数的密钥后,将密钥保存在一个 16位字符数组c 中,通过ToEr 函数将之变为二进制数。
ToEr 函数输入为字符数组,通过switch 语句逐个检查字 符数组的每一位,将对应的四位二进制数存在 64位布尔数组k 中。
64 bit 密钥去掉每个字节的最高位得到 56 bit 密钥输入,通过置换选择1变换得到C 0和D 。
各28 bit ,通过Zhihuan_1函数实现置换选择一。
Zhihuan_1函数输入为二进制密钥数组k[64],输出为C0和DO,将C0 D0分别储存在28位布尔数组C 、D 中 函数采用查表方式生成C0和D0b根据迭代的轮数确定C 和D 移位循环的位数,主程序中利用一个 16位整形数组来 存放每一次循环左移的位数。
循环左移通过 Xu nH uan 函数实现,函数输入为循环位数和 长度为28的布尔数组(C 或者D ),函数运行一次只能改变一个布尔数组的值。
为了减 低编程复杂度,程序使用串行方法,分两次进行 C 、D 的移位。
每完成一次C 和D 的移位,进行一次置换选择二。
置换选择二利用 zhihuan_2函数 完成。
思想和Zhihuan_1函数类似。
zhihuan_2函数输入为移位后的 C 、D, zhihuan_2 函数将圈子密钥存放在16*48的二维布尔数组kk[17][49] 中。
kk[i][48] 表示第i 圈的 圈子密钥。
原理图如图1所示。
脱密(o=0时)需要将圈子密钥交换,此时可利用kk[0][49]充当中间变量,无需定义新的变量减少了系统开销。
图1圈子密钥生成算法密钥 k 1C 16D 16k 2{置换选择 2”k 163、16圈迭代DES的每一圈迭代采用的是Feistel模型,先将初始置换后的明文mip数组分成L 和R两部分,先将R的内容放在等长的布尔数组 T中,最后时需要将L的值赋为T。
之后进入F函数,F函数原理如图2。
图2 F函数原理图程序中的F函数输入有初始置换结果的右半部分 R圈子密钥kk、迭代圈数i。
输出保存在R中。
先将输入的R通过查表的方法进行E拓展,结果保存在48位布尔数组a 中。
再将a与圈子密钥k按位模二加。
结果保存在a中。
接下来将a分成8组,分别进入8个S盒。
用for控制循环8次,每次操作选用6 位二进制代码的开头一位和最后一位转化成十进制数,控制 S盒的行数,再将6位二进制代码的中间四位转化成十进制数,控制 S盒的列数。
进入第几个S盒有迭代圈数i确定。
取到S盒中的十进制数后,将它转化成二进制数,储存在 32位布尔数组T中,在使用查表法完成P盒置换,最终结果保存在R中。
最后将L与R按位模二加,得到新的R,完成一次迭代。
4、逆初始置换16次迭代后,先将L16和R16连接起来,保存到64位布尔数组m中,m之前用于保存明文,这样减小了程序占用的空间。
另外,为了保证加脱密算法的一致性,迭代时最后一圈不需要交换L与R,但程序中为了简化编程复杂度,在迭代时仍然交换了L与R。
所以在连接时需要再次交换 L与R。
所以m的高32位应储存R,低32位应储存L。
逆初始置换原理同初始置换步骤,不再赘述。
四、取得的成果利用密钥 201601211438FBCA寸明文 81623317 加密,密文为 6B217C871EAE79D2HI果如图3所示。
图3 DES加密结果图利用密钥 201601211438FBCA寸密文 6B217C871EAE79D脱密,明文为 81623317。
结果如图4所示。
B " D:^C\Deb u g \m imaxu e2 next"图4 DES脱密结果图变换不同明文及密钥,均可以正常加脱密。
在报告中不再罗列五、心得体会DES算法是一种分组密码算法,本人通过对一个明文分组的加脱密进行编程,耗时近一个月,独立完成了次算法的 C++实现。
本人的程序不同于网上找的 DES算法程序,网上的大多数程序的密文都是以ASCII 码来输出的。
但是,这样输出的结果有很多乱码出现。
因为ASCII 码只有在小范围内输出的结果是正常的字母、数字或者符号(从 33 至 127),如果按 ASCII 输出乱码密文,脱密者就很难键入这些密文,只能通过复制粘贴进行。
而VC6.0的环境在控制台中很难进行复制操作,这样如果不借助文件,就很难完成密文的脱密。
而密文按 16进制输出就不存在这个问题。
二进制串与 ASCII 码、16进制数之间的转化也是实验的难点之一。
C 语言的课上没有讲过位运算的相关知识,本人只能通过除以二取余、查表等笨办法进行转化。
同样,密钥选用 16进制也是一个道理,如果只用字符输入密钥,密钥的每八位就会局限在00100001(33)至 01111111(127)范围之内,超过范围就无法用键盘进行输入密钥,这样破译者如果看到了加密程序源代码,相应的穷尽时间会减少。
通过本次编程,我发现我对 C/C++语言的掌握还是不够,尤其是涉及到位运算。
我也会找机会自学这一部分内容。
六、附录程序代码:#include <iostream> using namespace std;void ToEr(char c[],bool k[]){int i,j;j=0;for(i=1;i<=16;i++){switch (c[i]){case '0':k[j++]=0;k[j++]=0;k[j++]=0;break;case '1':k[j++]=0;k[j++]=0;k[j++]=0;k[j++]=1; break; case '2':k[j++]=0;k[j++]=0;k[j++]=1;k[j++]=0; break; case '3':k[j++]=0;k[j++]=0;k[j++]=1;k[j++]=1;break;case '4':k[j++]=0;k[j++]=1;k[j++]=0;k[j++]=0;break;case '5': k[j++]=0;k[j++]=0;k[j++]=1;break; case '6': k[j++]=0; k[j++]=1; k[j++]=1; k[j++]=0;break; case '7': k[j++]=0; k[j++]=1; k[j++]=1; k[j++]=1;break; case '8': k[j++]=1; k[j++]=0; k[j++]=0; k[j++]=0;break; case '9': k[j++]=1; k[j++]=0; k[j++]=0; k[j++]=1;break; case 'A': k[j++]=1; k[j++]=0;k[j++]=1;k[j++]=0;break; case 'B': k[j++]=1; k[j++]=0; k[j++]=1; k[j++]=1;break; case 'C': k[j++]=1; k[j++]=1; k[j++]=0; k[j++]=0;break; case 'D': k[j++]=1; k[j++]=1; k[j++]=0; k[j++]=1;break; case 'E': k[j++]=1; k[j++]=1; k[j++]=1; k[j++]=0;break; case 'F': k[j++]=1; k[j++]=1;k[j++]=1;k[j++]=1;break;}}// for (i=0;i<64;i++) cout<<k[i];// cout<<endl;}void MtoEr(char asc[],bool m[]){int i,j,flag,f;int as[9];bool z[9]={0},t;for(i=1;i<=8;i++) as[i] = (int)asc[i];for (i=1;i<=8;i++){f=1;flag = 8 * (i-1);while(as[i]!=0){z[f] = as[i] % 2;as[i] /= 2;f++;}// for(j=1;j<=8;j++) cout<<z[j];//cout<<endl;for(j=1;j<=4;j++) {t = z[j];z[j] = z[9-j];z[9-j] = t;} // z[1] = 0;for(j=1;j<=8;j++) m[flag+j] = z[j]; for(j=1;j<=8;j++) z[j]=0;}// for(j=1;j<=64;j++) cout<<m[j];// cout<<endl;}void IP(bool m[],bool mip[]){int ip[64]={57, 49, 41, 33, 25, 17, 9, 1,59, 51, 43, 35, 27, 19, 11, 3,61, 53, 45, 37, 29, 21, 13, 5,63, 55, 47, 39, 31, 23, 15, 7,56, 48, 40, 32, 24, 16, 8, 0,58, 50, 42, 34, 26, 18, 10, 2,60, 52, 44, 36, 28, 20, 12, 4,62, 54, 46, 38, 30, 22, 14, 6};for (int i=1;i<=64;i++) mip[i]=m[ip[i-1]+1];}void IP2(bool m[],bool mip[]){int ip[64]={39, 7, 47, 15, 55, 23, 63, 31,38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29,36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27,34, 2, 42, 10, 50, 18, 58, 26,33, 1, 41, 9, 49, 17, 57, 25,32, 0, 40, 8, 48, 16, 56, 24};for (int i=1;i<=64;i++) mip[i]=m[ip[i-1]+1];}void Zhihuan_1(bool k[],bool C[],bool D[]){int a[28]={57,49,41,33,25,17,9,1,58,50,42,34,26,18,10,2,59,51,43,35,27,19,11,3,60,52,44,36};int b[28]={63,55,47,39,31,23,15,7,62,54,46,38,30,22,14,6,61,53,45,37,29,21,13,5,28,20,12,4};int i;for(i=1;i<=28;i++) C[i]=k[a[i-1]];for(i=1;i<=28;i++) D[i]=k[b[i-1]];// for(i=1;i<=28;i++) cout<<C[i]; cout<<endl; // for(i=1;i<=28;i++) cout<<D[i]; cout<<endl;void zhihuan_2(bool C[],bool D[],bool k[][49],int q) int a[48]={13,16,10,23,0,4,2,27,14,5,20,9,22,18,11,3,25,7,15,6,26,19,12,1,40,51,30,36,46,54,29,39,50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31};int i;bool T[57];for (i=1;i<=56;i++){if(i<=28) T[i] = C[i];else T[i] = D[i-28];}for(i=1;i<=48;i++)k[q+1][i]=T[a[i-1]+1];// for (i=1;i<=48;i++) cout<<k[q+1][i]; cout<<endl; }void XunHuan(int x,bool C[]){int i;bool T[29];for(i=1;i<29;i++) T[i] = C[(i+x)%28+1];for(i=1;i<29;i++) C[i] = T[i];void F(bool R[],bool kk[][49],int x){int E[48]={31, 0, 1, 2, 3, 4,3, 4, 5, 6, 7, 8,7, 8, 9, 10, 11, 12,11, 12, 13, 14, 15, 16,15, 16, 17, 18, 19, 20,19, 20, 21, 22, 23, 24,23, 24, 25, 26, 27, 28,27, 28, 29, 30, 31, 0};int S[8][4][16]={{{14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7},{ 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8},{ 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0},{15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13} },{{15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10},{ 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5},{ 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15},{13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9} },{{10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8},{13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1},{13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7},{ 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12} },{{ 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15},{13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9},{10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4},{ 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14} },{{ 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9},{14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6},{4, 2, 1, 11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14},{11,8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3} },{{12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11},{10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8},{ 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6},{ 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13} },{{ 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1},{13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6},{ 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2},{ 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12} },{{13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7},{ 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2},{ 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8},{ 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11} }};int i,j,p,a1,a2,k[8];bool a[49],b[33];for (i=1;i<=48;i++) a[i] = R[E[i-1]+1];// for (i=1;i<=48;i++) cout<<a[i];for (i=1;i<=48;i++) a[i]A= kk[x] [i];// for (i=1;i<=48;i++) cout<<a[i];p=1;for (i=0;i<8;i++){a1 = a[p]*2+a[p+5];// 左右两位换成十进制数a2 = a[p+1]*8+a[p+2]*4+a[p+3]*2+a[p+4]; // 中间 4位换成十进制数// cout<<a1<<endl;// cout<<a2<<endl;p += 6;k[i] = S[i][a1][a2];// cout<<k[i]<<endl;}p=1;for (i=0;i<8;i++){switch (k[i]){case 0: b[p++] = 0;b[p++] = 0;b[p++] = 0;break;case 1: b[p++] = 0;b[p++] = 0;b[p++] = 0;b[p++] = 1;break; case 2: b[p++] = 0;b[p++] = 0;b[p++] = 1;b[p++] = 0;break; case 3: b[p++] = 0;b[p++] = 0;b[p++] = 1;b[p++] = 1;break;case 4: b[p++] = 0;b[p++] = 1;b[p++] = 0;b[p++] = 0;break;case 5: b[p++] = 0;b[p++] = 1;b[p++] = 0;b[p++] = 1;break;case 6: b[p++] = 0;b[p++] = 1;b[p++] = 1;b[p++] = 0;break;case 7: b[p++] = 0;b[p++] = 1;b[p++] = 1;case 8: b[p++] = 1; b[p++] = 0; b[p++] = 0; b[p++] = 0;break; case 9: b[p++] = 1;b[p++] = 0;b[p++] = 0;b[p++] = 1;break;case 10: b[p++] = 1;b[p++] = 0;b[p++] = 1;b[p++] = 0;break;case 11: b[p++] = 1;b[p++] = 0;b[p++] = 1;b[p++] = 1;break;case 12: b[p++] = 1;b[p++] = 1;b[p++] = 0;b[p++] = 0;break;case 13: b[p++] = 1;b[p++] = 1;b[p++] = 0;b[p++] = 1;break;case 14: b[p++] = 1;b[p++] = 1;b[p++] = 1;b[p++] = 0;break;case 15: b[p++] = 1;b[p++] = 1;b[p++] = 1;break;}}bool T[33];for(i=1;i<=32;i++) T[i]=b[i];int P[32]={15,6,19,20,28,11,27,16,0,14,22,25,4,17,30,9,1,7,23,13,31,26,2,8,18,12,29,5,21,10,3,24};for(i=1;i<=32;i++) R[i]=T[P[i-1]+1]; }void main(){ char c[17],asc[9];int i,j,mout[17];bool k[65],kk[17][49],C[29],D[29],m[65],mip[65],L[33],R[33],T[33]; //k二进制密钥,kk存放16圈的圈子密钥,m存放明文,mip存放明文初始变换后 int z[16]={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};int o; //C密钥生产算法的左右两个部分。