DES
来源:互联网 发布:特朗普增加军费知乎 编辑:程序博客网 时间:2024/04/29 17:19
#include<bits/stdc++.h>using namespace std;#define ENCODE true#define DECODE falseconst int//初始置换函数IPIP[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},//末置换FP[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},//密钥每次移动位数KM[16] ={1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 ,1 , 2 , 2 , 2 , 2 , 2 , 2 , 1},//密钥置换PC-1PC1[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-2PC2[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},//S盒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} }},//扩展置换E盒E_BOX[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},//P盒P_BOX[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};bool KEY[16][48]; //16个子密钥void Permutation(bool x[],int length,const int BOX[]) //置换函数,参数:待置换数据,长度,置换盒子{ bool *tmp=new bool[length]; for(int i=0;i<length;++i) tmp[i]=x[BOX[i]-1]; for(int i=0;i<length;++i) x[i]=tmp[i];}void GetKey(bool key[64]) //生成子密钥{ bool C[60],D[60]; //开两倍大小的数组是为了方便实现循环移位 int i,j,st; memset(KEY,0,sizeof(KEY)); for(i = 0; i < 28; ++i) //PC-1置换,得到28位的C0,D0 { C[i+28] = C[i] = key[PC1[i]-1]; D[i+28] = D[i] = key[PC1[i+28]-1]; } st = 0; //累计移动位数(C和D不变,为基准,加上st实现多次移位) for(i = 0; i < 16; ++i) //16次置换,得到16个子密钥 { st += KM[i]; for(j = 0; j < 48; ++j) KEY[i][j] = (PC2[j] < 28)?C[PC2[j] + st - 1]:D[PC2[j] - 29 + st]; }}void Work(bool L[32],bool R[32],bool KEY[48],int cnt) //一轮DES{ bool X[48],RES[32]; memset(RES,0,sizeof(RES)); memset(X,0,sizeof(X)); int i,j,a,b,st,tmp; for(i = 0; i < 48; ++i) //R扩展置换得到48位,和子密钥异或 X[i] = R[E_BOX[i]-1] ^ KEY[i]; //将异或得到的结果压缩置换成32位 for(i = 0; i < 8; ++i) //分为8个6位的块 { st = i * 6; //每个块的起始位置 a = (X[st] << 1) + X[st + 5]; //取第1位和第6位(2进制),构成行数 //中间4位构成列数 b = (X[st + 1] << 3) + (X[st + 2] << 2) + (X[st + 3] << 1) + X[st + 4]; tmp = S_BOX[i][a][b]; //查找S盒 st = i * 4; //保存结果的数组当前存放位置的开始位置 for(j = 0; j < 4; ++j) //拼接每次的tmp(转为4位二进制)到RES中 RES[st + (3 - j)] |= (tmp >> j)&1; } Permutation(RES,32,P_BOX); for(i=0;i<32;++i) L[i] ^= RES[i]; if (cnt == 15) return ; //注意这里!!!!!!!! //最后一轮不需要交换L和R,原因是最后拼接为64位的时候 //是把L作为低32位,R作为高32位的!!!! for(i=0;i<32;++i) swap(L[i],R[i]);}void DES(char txt[10],char enc[10],bool flag) //DES函数,加解密共用,参数为64位明文/密文、和存放结果的数组、加解密标记{ int i,j; bool L[32],R[32]; bool pt[64]; for(i = 0; i < 8; ++i) for(j = 7; j >= 0; --j) //8位字符转换为64位2进制 pt[i * 8 + (7 - j)] = (txt[i] >> j) & 1; Permutation(pt,64,IP); //初始置换 for(i = 0; i < 32; ++i) //拆分为两个32位 L[i] = pt[i],R[i] = pt[i + 32]; if(flag==ENCODE) //加密 { for(i = 0; i < 16; ++i) //16轮迭代 Work(L,R,KEY[i],i); } else //解密 { for(i = 0; i < 16; ++i) //16轮迭代 Work(L,R,KEY[15-i],i); } for(i = 0; i < 32; ++i) //拼接得到64位,注意,这里的L实际上是R16,R为R15,即L16 pt[i] = L[i],pt[i + 32] = R[i]; Permutation(pt,64,FP); //末置换 for(i = 0; i < 8; ++i) for(j = 7; j >= 0; --j) enc[i] |= pt[i * 8 + (7 - j)] << j;}char Fpt[1005],Fct[1005],key[1005];void solve(bool flag){ int tmp,i,j; bool sk[64]; char txt[10],res[10]; FILE *R,*W; for(i = 0; i < 8; ++i) for(j = 7; j >= 0; --j) sk[i * 8 + (7 - j)] = (key[i] >> j) & 1; //密钥转为64位2进制 GetKey(sk); R = flag==ENCODE?fopen(Fpt,"r"):fopen(Fct,"r"); W = flag==ENCODE?fopen(Fct,"w"):fopen(Fpt,"w"); if(R==NULL||W==NULL) {puts("文件打开失败!"); return;} flag==ENCODE?puts("加密结果如下:"):puts("解密结果如下:"); while((tmp = fread(txt,sizeof(txt[0]),8,R))) //每次读取8个字符到txt中 { for(i = tmp; i < 8; ++i) txt[i] = 0; //不满8位,在末尾补0 memset(res,0,sizeof(res)); DES(txt,res,flag); fwrite(res,sizeof(res[0]),8,W); printf("%s",res); } puts(""); fclose(W); fclose(R);}int main(){ int ch; while(true) { puts("请选择:1.加密 2.解密"); scanf("%d",&ch); printf("请输入存放明文的文件名(含后缀):"); scanf("%s",Fpt); printf("请输入存放密文的文件名(含后缀):"); scanf("%s",Fct); printf("请输入密钥:"); scanf("%s",key); int L=strlen(key); if(L>8) {puts("密钥长度不符合要求");continue;} else if(L<8) //密钥长度不足,后面添0 { for(int i=L;i<8;++i) key[i]=0; } if (ch==1) solve(ENCODE); else if (ch==2) solve(DECODE); else break; } return 0;}
0 0
- des
- des
- DES
- DES
- DES
- DES
- des
- DES
- des
- DES
- DES
- DES
- DES
- DES
- DES
- des
- DES
- DES
- 【数据结构】之二叉树的java实现
- shell脚本编程<二>:if-then,case结构化命令
- 【数据结构】之链栈的java实现
- 2015年浅度总结
- 写在前面
- DES
- Linux apt-get
- 【数据结构】之队列的java实现(一)
- windows和linux注册动态链接库的方法
- NSOperation的其他设置
- 《挑战程序设计竞赛》3.1.2 二分搜索-最大化平均值 POJ2976 3111
- RSA
- 【数据结构】之队列的java实现(二)
- Angularjs 中的 controller