www.pudn.com > des.zip > des.cpp
using namespace std; #include "stdafx.h" #include "memory.h" #include#include "stdio.h" #include "string.h" #include "fstream" enum {ENCRYPT,DECRYPT}; //ENCRYPT==0 表示加密DECRYPT==1表示解密 char bufer[1024]; //定义了一个1024个字符组来充当计算过程中的临时变量 char key[64]; //定义了一个接受密匙的字符组 char context[1024]; //定义了一个1024个字符的组来存储明文 和密文的空间 //DES的初始置换IP表 const static char IP_Table[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 }; //DES的IP逆置换表 const static char IPR_Table[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 }; //DES加密过程的选为表E static const char E_Table[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 }; // 32-bit permutation function P used on the output of the S-boxes const static char P_Table[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 }; // 置换选择表PC-1 const static char PC1_Table[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 }; //置换选择表PC-2 const static char PC2_Table[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, 45, 33, 48, 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 }; //循环左移运算表 const static char LOOP_Table[16] = { //1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 1,1,2,2,2,2,2,2,1, 2, 2, 2, 2, 2, 2,1 }; //S盒运算 const static char S_Box[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 }; typedef bool (*PSubKey)[16][48]; //这里用bool来表示 一个位 bool Des_Go(char *Out,char *In,long datalen,const char *Key,int keylen,bool Type = ENCRYPT); /* 调用DES Out输出缓冲区 In 是输入的字符组 可能是明文也可能是密文,Key是密匙,keylen是密匙的长度,Type表示解密或加密 */ static void DES(char Out[8], char In[8], const PSubKey pSubKey, bool Type);//标准DES加/解密 static void SetKey(const char* Key, int len); // 设置密钥 key 字符组 len是key字符组的长度 static void SetSubKey(PSubKey pSubKey, const char Key[8]);// 设置子密钥 static void F_func(bool In[32], const bool Ki[48]);// f 函数 static void S_func(bool Out[32], const bool In[48]);// 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);// 位组转换成字节组 void savefile(const char * s,char c,char *fn);//用来进行文档的写 ////////////////////////////////////////////////////////////////////////// static bool SubKey[2][16][48];// 16圈子密钥 static char Tmp[256], deskey[16]; /* 主体加密解密函数 */ bool Des_Go(char *Out, char *In, long datalen, const char *Key, int keylen, bool Type) { if( !( Out && In && Key && (datalen=(datalen+7)&0xfffffff8) ) ) return false; SetKey(Key, keylen); for(long i=0,j=datalen>>3; i 16?16:len); //设置子密匙 SetSubKey(&SubKey[0], &deskey[0]); } //每八位一组的DES运算 void DES(char Out[8], char In[8], const PSubKey pSubKey, bool Type) { static bool M[64], tmp[32], *Li=&M[0], *Ri=&M[32]; ByteToBit(M, In, 64); Transform(M, M, IP_Table, 64); if( Type == ENCRYPT ){ //进行16轮迭代进行加密 for(int i=0; i<16; ++i) { memcpy(tmp, Ri, 32); F_func(Ri, (*pSubKey)[i]); Xor(Ri, Li, 32); memcpy(Li, tmp, 32); } }else{ //进行16轮逆迭代进行解密 for(int i=15; i>=0; --i) { memcpy(tmp, Li, 32); F_func(Li, (*pSubKey)[i]); Xor(Li, Ri, 32); memcpy(Ri, tmp, 32); } } Transform(M, M, IPR_Table, 64); BitToByte(Out, M, 64); } void SetSubKey(PSubKey pSubKey, const char Key[8]) { // static bool K[64], *KL=&K[0], *KR=&K[28]; //把字节转化成位数据 ByteToBit(K, Key, 64); //通过PC-1置换选择表进行置换 Transform(K, K, PC1_Table, 56); //进行16轮的迭代 for(int i=0; i<16; ++i) { //对左部的28位进行 左循环 RotateL(KL, 28, LOOP_Table[i]); //对右部的28位进行 左循环 RotateL(KR, 28, LOOP_Table[i]); //根据 PC-2置换选择表进行置换 Transform((*pSubKey)[i], K, PC2_Table, 48); } } //进行F函数运算 void F_func(bool In[32], const bool Ki[48]) { static bool MR[48]; Transform(MR, In, E_Table, 48); Xor(MR, Ki, 48); S_func(In, MR); Transform(In, In, P_Table, 32); } //进行S函数运算 void S_func(bool Out[32], const bool In[48]) { for(char i=0,j,k; i<8; ++i,In+=6,Out+=4) { j = (In[0]<<1) + In[5]; k = (In[1]<<3) + (In[2]<<2) + (In[3]<<1) + In[4]; ByteToBit(Out, &S_Box[i][j][k], 4); } } //通过指定的置换表进行数据置换 void Transform(bool *Out, bool *In, const char *Table, int len) { for(int i=0; i >3]>>(i&7)) & 1;//通过移位获取每一个字符的第一个位的值 } //把位转化为数组 void BitToByte(char *Out, const bool *In, int bits) { memset(Out, 0, bits>>3); for(int i=0; i >3] |= In[i]<<(i&7); } int main() { memset(key,0,sizeof(key)); //把密匙空间清空并置为0 FILE *openfile; int contextCount=0; char pn[20],cn[20]; char chooser; int flag=1; while(flag) { memset(bufer, 0, sizeof(bufer)); //把缓存区等清空并置为0 memset(context,0,sizeof(context));//把内容空间清空并置为0 printf("请选择下面的操作步骤 E 加密运算 D解密运算 X退出\n"); int keyCount=sizeof(key); scanf("%c",&chooser); getchar(); //接受回车符 switch(chooser) { case 'E': case 'e': { printf("请输入要加密的文件的文件名:"); scanf("%s",pn); getchar(); printf("请输入密钥:"); scanf("%s",key); getchar(); openfile=fopen(pn,"rb");//打开明文内容 if(!openfile) { printf("明文文件打开失败!\n"); return 0; } contextCount=fread(context,sizeof(char),1024,openfile);//获取明文文件内容并得到实际内容的大小 printf("明文的大小为:%d\n明文的内容为:\n%s\n\n",contextCount,context); fclose(openfile); openfile=0; strcpy(bufer,context); Des_Go(bufer,bufer,contextCount,key,keyCount,ENCRYPT); printf("加密后的内容为:\n%s\n\n",bufer); printf("是否保存到文件中(Y,N):"); char c; scanf("%c",&c); getchar(); if(c=='y'||c=='Y') { printf("请输入文件名:"); memset(cn,NULL,sizeof(cn)); scanf("%s",cn); getchar(); savefile(bufer,'E',cn); } printf("\n"); break; }; case 'D': case 'd': { printf("请输入要解密的文件的文件名:"); scanf("%s",cn); getchar(); printf("请输入密钥:"); scanf("%s",key); getchar(); openfile=fopen(cn,"rb");//打开密文内容 if(!openfile) { printf("密文文件打开失败!\n"); return 0; } contextCount=fread(context,sizeof(char),1024,openfile);//获取明文文件内容并得到实际内容的大小 printf("密文的大小为:%d\n密文的内容为:\n%s\n\n",contextCount,context); fclose(openfile); openfile=0; strcpy(bufer,context); Des_Go(bufer,bufer,contextCount,key,keyCount,DECRYPT); printf("解密后的内容为:\n%s\n\n",bufer); printf("是否保存到文件中(Y,N):"); char c; scanf("%c",&c); getchar(); if(c=='y'||c=='Y') { printf("请输入文件名:"); memset(pn,NULL,sizeof(pn)); scanf("%s",pn); getchar(); savefile(bufer,'D',pn); } printf("\n"); break; } case 'X': case 'x': {flag=0;} } } return 1; } void savefile(const char* s,char c,char *fn) { FILE *f; if(c=='E') { f=fopen(fn,"wb"); if(!f) { printf("打开文件失败!\n"); return; } if(fwrite(s,sizeof(char),strlen(s),f)!=strlen(s)) { printf("写入文件失败!\n"); } printf("写入文件成功!\n") ; } else { f=fopen(fn,"wb"); if(!f) { printf("打开文件失败!\n"); return; } if(fwrite(s,sizeof(char),strlen(s),f)!=strlen(s)) { printf("写入文件失败!\n"); } printf("写入文件成功!\n") ; } fclose(f); }