[实验项目]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);在最后一轮左与右半部分并未变换,而是直接将R16L16并在一起作为未置换的输入。第三阶段:逆(初始)置换。他是初始置换IP的逆置换,记为IP-1。在对16次迭代的结果(R16L16)再使用逆置换IP-1后,得到的结果即可作为DES加密的密文Y输出,即Y=IP-1(R16L16)。2.DES解密过程:DES的解密算法与其加密算法使用的算法过程相同。两者的不同之处在于解密时子密钥Ki的使用顺序与加密时相反,如果子密钥为K1K2…K16,那么解密时子密钥的使用顺序为K16K15…K1,即使用DES解密算法进行解密时,将以64位密文作为输入,第1次迭代运算使用子密钥K16,第2次迭代运算使用子密钥K15,……,第16次迭代使用子密钥K1,其它的运算与加密算法相同。这样,最后输出的是64位明文。[设计内容][设计过程]/*-------------------------------------------------------DataEncryptionStandard56位密钥加密64位数据--------------------------------------------------------*/#includestdlib.h#includestdio.h#includebool.h//位处理#includetables.hvoidByteToBit(bool*DatOut,char*DatIn,intNum);//字节到位voidBitToByte(char*DatOut,bool*DatIn,intNum);//位到字节voidBitToHex(char*DatOut,bool*DatIn,intNum);//二进制到十六进制64位to4*16字符voidHexToBit(bool*DatOut,char*DatIn,intNum);//十六进制到二进制voidTablePermute(bool*DatOut,bool*DatIn,constchar*Table,intNum);//位表置换函数voidLoopMove(bool*DatIn,intLen,intNum);//循环左移Len长度Num移动位数voidXor(bool*DatA,bool*DatB,intNum);//异或函数voidS_Change(boolDatOut[32],boolDatIn[48]);//S盒变换voidF_Change(boolDatIn[32],boolDatKi[48]);//F函数voidSetKey(charKeyIn[8]);//设置密钥voidPlayDes(charMesOut[8],charMesIn[8]);//执行DES加密voidKickDes(charMesOut[8],charMesIn[8]);//执行DES解密intmain(){inti=0;charMesHex[16]={0};//16个字符数组用于存放64位16进制的密文charMyKey[8]={0};//初始密钥8字节*8charYourKey[8]={0};//输入的解密密钥8字节*8charMyMessage[8]={0};//初始明文/*-----------------------------------------------*/printf(Welcome!PleaseinputyourMessage(64bit):\n);gets(MyMessage);//明文printf(PleaseinputyourSecretKey:\n);gets(MyKey);//密钥while(MyKey[i]!='\0')//计算密钥长度{i++;}while(i!=8)//不是8提示错误{printf(PleaseinputacorrectSecretKey!\n);gets(MyKey);i=0;while(MyKey[i]!='\0')//再次检测{i++;}}SetKey(MyKey);//设置密钥得到子密钥KiPlayDes(MesHex,MyMessage);//执行DES加密printf(YourMessageisEncrypted!:\n);//信息已加密for(i=0;i16;i++){printf(%c,MesHex[i]);}printf(\n);printf(\n);printf(PleaseinputyourSecretKeytoDeciphering:\n);//请输入密钥以解密gets(YourKey);//得到密钥SetKey(YourKey);//设置密钥KickDes(MyMessage,MesHex);//解密输出到MyMessageprintf(DecipheringOver!!:\n);//解密结束for(i=0;i8;i++){printf(%c,MyMessage[i]);}printf(\n);system(pause);/*------------------------------------------------*/}/*-------------------------------把DatIn开始的长度位Len位的二进制复制到DatOut后--------------------------------*/voidBitsCopy(bool*DatOut,bool*DatIn,intLen)//数组复制OK{inti=0;for(i=0;iLen;i++){DatOut[i]=DatIn[i];}}/*-------------------------------字节转换成位函数每8次换一个字节每次向右移一位和1与取最后一位共64位--------------------------------*/voidByteToBit(bool*DatOut,char*DatIn,intNum)//OK{inti=0;for(i=0;iNum;i++){DatOut[i]=(DatIn[i/8](i%8))&0x01;}}/*-------------------------------位转换成字节函数字节数组每8次移一位位每次向左移与上一次或---------------------------------*/voidBitToByte(char*DatOut,bool*DatIn,intNum)//OK{inti=0;for(i=0;i(Num/8);i++){DatOut[i]=0;}for(i=0;iNum;i++){DatOut[i/8]|=DatIn[i](i%8);}}/*----------------------------------二进制密文转换为十六进制需要16个字符表示-----------------------------------*/voidBitToHex(char*DatOut,bool*DatIn,intNum){inti=0;for(i=0;iNum/4;i++){DatOut[i]=0;}for(i=0;iNum/4;i++){DatOut[i]=DatIn[i*4]+(DatIn[i*4+1]1)+(DatIn[i*4+2]2)+(DatIn[i*4+3]3);if((DatOut[i]%16)9){DatOut[i]=DatOut[i]%16+'7';//余数大于9时处理10-15toA-F}//输出字符else{DatOut[i]=DatOut[i]%16+'0';//输出字符}}}/*---------------------------------------------十六进制字符转二进制----------------------------------------------*/voidHexToBit(bool*DatOut,char*DatIn,intNum){inti=0;//字符型输入for(i=0;iNum;i++){if((DatIn[i/4])'9')//大于9{DatOut[i]=((DatIn[i/4]-'7')(i%4))&0x01;}else{DatOut[i]=((DatIn[i/4]-'0')(i%4))&0x01;}}}//表置换函数OKvoidTablePermute(bool*DatOut,bool*DatIn,constchar*Table,intNum){inti=0;staticboolTemp[256]={0};for(i=0;iNum;i++)//Num为置换的长度{Temp[i]=DatIn[Table[i]-1];//原来的数据按对应的表上的位置排列}BitsCopy(DatOut,Temp,Num);//把缓存Temp的值输出}//子密钥的移位voidLoopMove(bool*DatIn,intLen,intNum)//循环左移Len数据长度Num移动位数{staticboolTemp[256]={0};//缓存OKBitsCopy(Temp,DatIn,Num);//将数据最左边的Num位(被移出去的)存入TempBitsCopy(DatIn,DatIn+Num,Len-Num);//将数据左边开始的第Num移入原来的空间BitsCopy(DatIn+Len-Num,Temp,Num);//将缓存中移出去的数据加到最右边}//按位异或voidXor(bool*DatA,bool*DatB,intNum)//异或函数{inti=0;for(i=0;iNum;i++){DatA[i]=DatA[i]^DatB[i];//异或}}//输入48位输出32位与Ri异或voidS_Change(boolDatOut[32],boolDatIn[48])//S盒变换{inti,X,Y;//i为8个S盒for(i=0,Y=0,X=0;i8;i++,DatIn+=6,DatOut+=4)//每执行一次,输入数据偏移6位{//每执行一次,输出数据偏移4位Y=(DatIn[0]1)+DatIn[5];//af代表第几行X=(DatIn[1]3)+(DatIn[2]2)+(DatIn[3]1)+DatIn[4];//bcde代表第几列ByteToBit(DatOut,&S_Box[i][Y][X],4);//把找到的点数据换为二进制}}//F函数voidF_Change(boolDatIn[32],boolDatKi[48])//F函数{staticboolMiR[48]={0};//输入32位通过E选位变为48位TablePermute(MiR,DatIn,E_Table,48);Xor(MiR,DatKi,48);//和子密钥异或S_Change(DatIn,MiR);//S盒变换TablePermute(DatIn,DatIn,P_Table,32);//