参考资料:

1.计算机与软件学院实验报告管理系统资料

2.强烈推荐观看:《信息安全技术》课程微课设计

简介

什么是DES

DES全称为Data Encryption Standard,即数据加密标准,是一种使用密钥加密的块算法,1977年被美国联邦政府的国家标准局确定为联邦资料处理标准(FIPS),并授权在非密级政府通信中使用,随后该算法在国际上广泛流传开来。需要注意的是,在某些文献中,作为算法的DES称为数据加密算法(Data Encryption Algorithm,DEA),已与作为标准的DES区分开来。

DES的安全性

主要来源于以下几个方面:加密之初提供一个64位的密钥(去除8位奇偶校验位后,用于加密解密的是56位),而真正加密时,用到了16个48位的子密钥,子密钥的形成过程用到反反复复的移位和数组的置换,因此仅获得了最初的密钥仍然不能破解密文;同样在利用16个子密钥对64位的0、1序列加密时,也不是简单的异或,而是进行多次复杂的数组扩充,以及元素位置置换,因此即使获得了16个子密钥还是不能破解原文。

0.加密过程概览

graph TD
A(64 bit 原文)
A --> B[初始置换]
B --> |K1| C[01轮加密]
C --> |K2| D[02轮加密]
D --> |K3| E[03轮加密]
E --> |K...| F[......]
F --> |K16| G[16轮加密]
G --> H[终止置换]
H --> I(64 bit 密文)

DES加密以8个字母为一个单位,每个字母由8位二进制0,1表示。64 bit plaintext 即一个单位的明文。

第一步

初始置换:把64bit明文通过IP_1置换表打乱顺序

第二步

对64bit明文进行16轮加密(每轮的的秘钥都不同K1K2...K16)

第三步

终止置换:把加密后的64bit密文通过IP_2置换表打乱顺序

1.第一步和第三步详解

初始置换

终止置换

什么是置换?

就是把字符按照置换表格重新排顺序

如图对于一组数据

初始置换置换表(IP_1置换表)

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

原始数据

0 1 1 0 0 0 1 1 0 1 0 1 1 1 0 0
0 0 1 1 1 0 1 1 1 0 1 1 0 1 0 1
0 0 0 1 0 1 1 1 1 0 0 0 0 0 0 1
0 0 1 1 1 0 0 0 0 0 1 0 0 1 1 0

置换后

0 0 0 0 0 0 1 1 0 1 0 1 1 1 1 0
1 0 0 1 1 0 1 0 0 0 1 1 1 1 0 1
0 0 1 0 1 0 0 0 1 1 0 0 1 1 0 1
0 1 0 0 0 1 1 0 1 0 0 1 0 1 0 1

置换表第1个数为58,就把数据的第58位“0”放到这

置换表第2个数为50,就把数据的第50位“0”放到这

置换表第3个数为42,就把数据的第42位“0”放到这

...

置换表第64个数为7,就把数据的第7位“1”放到这

初始置换:明文按照置换表IP_1的第一次置换

终止置换: 明文被加密后按照置换表IP_2再次置换

当然两次用的置换表是不同的

2.第二步详解

16轮加密,每一轮的流程相同,但是所用到的子秘钥K不同。

流程图

我们把经过初始置换的64 bit明文记作Y0

graph TD
C{Y0}
C --> |选取左边32位| D[L]
C --> |选取右边32位| E{R}
E --> |复制一份R|F(直接作为下一轮的L)
E --> |骚操作1 E扩展置换| G[48 bit NR]
G-->|骚操作2 子秘钥K1加密| H[48 bit NR]
H-->|骚操作3 S盒压缩| I[32 bit NDS]
I-->|骚操作4 与L进行异或运算| J[32 bit NDS]
J-->K(作为下一轮的R)
Z[第一轮的加密过程]

接着换用不同的K2,K3,K4...k16完成16轮加密!

“骚操作1:E扩展置换”具体是怎样实现 32 bit——>48 bit 的?

我们来看看扩展置换表和普通置换表的差别



可以发现扩展置换表有重复部分,这样R中就会有部分数据被重复使用,从而达到扩展的效果

那么被重复使用的部分是随意选的吗,它有什么规律呢吗?



由图可知他是把32位数据分为8组,对每组的首尾两位进行了扩充。

“骚操作4:与L进行异或运算”具体是怎样实现的?

什么是异或运算呢?

1 xor 1 = 0

0 xor 0 = 0

1 xor 0 = 1

0 xor 1 = 1

我们会发现他和加法运算的区别就是,1+1=0, 这是因为二进制没有2导致的,开个玩笑哈哈哈

如下两个5位二进制序列进行异或运算

graph TD
A[A 00101]
B[B 10001]

对应位的01进行异或易得结果C

graph TD
C[C 10100]

对于32位的L与DNS异或运算也是同样的道理。

“骚操作2:子秘钥K1加密”具体是怎样实现的?

  • K的加密

    看过“骚操作4”,我们了解到了异或运算

    其实所谓的子秘钥就是一个01序列

    子秘钥加密就是用01序列k1与其进行异或运算

    因为此时的NR是48位,所以子秘钥K1就是48位的01序列。

    16个不同的子秘钥就是16个不同的48位的01序列。
  • K的产生

    我们知道16轮的加密需要16个不同的子密钥K,那么这16个密钥从何而来?这16个子密钥之间有什么关系呢?

    原来

    它是由一个密钥通过走位,咳咳...移位变换出来的

    初始密钥记作Y0,它由64位01序列组成,但其中8位用于奇偶校验,所以实际用于加密的只有56位。

    56位的密钥(K0)→左边为C0,右边为D0→将C0、D0移位I(i)位(i取值0-15)→C[16]、D[16]→将C[i]D[i]作为一个整体按PC-2变换,得到48位的K[i]。
graph LR
Z[子密钥的产生]
C(56 bits)
C -->|选取前28位| D[C0]
C -->|选取后28位| E[D0]
D -->| 移位I-i-位-i-分别取1到16之间的数|F[CI]
E -->| 移位I-i-位-i-分别取1到16之间的数|G[DI]
F -->x[CIDI]
G -->x[CIDI]
x -->| 整体PC_2置换 |K[48 bits]
K -->H(K1)
K -->I(K2)
K -->J(K3)
K -->Y(略)
K -->V(K14)
K -->W(K15)
K -->ZH(K16)

移位运算就是01序列的位置向前平移

graph LR
B(0000011)

移位1位

graph LR
B(0000110)

移位2位

graph LR
B(0011000)

I[i]是数组I[16]中的一个数,I[16]={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}

i取1时,I[1] = 1

C0和D0就要进行对应的移位1位运算。

像这样,i从1取到16就会得到16个子密钥

“骚操作3:S盒压缩”具体是怎样实现48 ——> 32的?

graph TD
C(48 bit NR)
C --> D[6位]
C --> E[6位]
C --> F[6位]
C --> G[6位]
C --> H[6位]
C --> I[6位]
C --> J[6位]
C --> K[6位]
D --> |s盒|M[4位]
E --> |s盒|N[4位]
F --> |s盒|O[4位]
G --> |s盒|P[4位]
H --> |s盒|Q[4位]
I --> |s盒|R[4位]
J --> |s盒|S[4位]
K --> |s盒|T[4位]
M --> W[32位]
N --> W[32位]
O --> W[32位]
P --> W[32位]
Q --> W[32位]
R --> W[32位]
S --> W[32位]
T --> W[32位]

可以看出48 bit NR 被分成了八个组 每组6位,6位被s盒搞成4位了

所以s盒部分发生了什么?

其实S盒就是一张数据表

对,长的就是这么丑

原来,

6位数的首尾两位组成了一个十进制数,作为表的 行

6位数的中间四位组成一个十进制数,作为表的 列

由行和列在表中可以确定一个值,把该值转换为4位二进制数



3.DES加密的C++编程实现

原理

DES子密钥的获得:

56位的密钥(K0)→左边为C0,右边为D0→将C0、D0移位I(i)次(i取值0-15)→C[16]、D[16]→将C[i]D[i]作为一个整体按PC-2变换,得到48位的K[i]。

利用K[i]加密的过程:

通过键盘输入8个字符,将字符对应的ASCII码值转换成0、1序列,作为待加密序列Y→通过IP将Y变成Y0→将变换后的数据Y0分为两部分,开始的32位称为L,最后的32位称为R→()将R通过E扩展成48位的序列NR→将NR与K[i](i的初始值为0,直到i=15结束)相异或结果仍然保存在NR→将NR分为8个6位长的部分,第1位到第6位称为B[0],第7位到第12位称为B[1],依此类推,第43位到第48位称为B[7→将B[J]的第1位和第6位组合为一个2位长度的变量M,M作为在S[J]中的行号。将B[J]的第2位到第5位组合,作为一个4位长度的变量N,N作为在S[J]中的列号。其中S[J]是一个有64个元素的序列,即S是一个二维数组,通过计算得来的M,N,以及当前B的序号J(J取值0-7),可以查询到S中对应的元素,并将S中的该元素,转换成二进制的四位0、1序列,存放在NDS中相应的四位中→将NDS与L相异或,结果仍然保留在NDS中→将R值赋给L,将NDS赋给R,回到()处开始循环→将最后一次得到的L、R作为一个整体利用序列IP_1扩展成64位的加密数据M。

解密的过程:

M利用逆IP_1变换得到L、R→()R赋值给tL,L值赋值给tR→tR按E扩展为NR→NR与K[i](i初始值为15,以后递减直到0结束)异或,结果保存在NR→利用S查询的方法得到NDS→将tL与NDS相异或,结果保留在tL中→将tL赋值给L,将tR赋值给R,回到()处开始循环→将最终的L、R按照逆变换IP得到原数据A。

运行效果

源码及解析

#include<iostream>
#include<cmath>
using namespace std;
/*=======================Loop_Move循环左移============================*/
void loop_move(int *p,int i)//p指向需要移位数组
{ if(i == 1)//左移1位
{
int temp;
temp = *(p+0);
for(int k = 0 ;k < 27; k++)
{
*(p+k) = *(p+k+1);
}
*(p+27) = temp; }
else//左移2位
{
int temp0;
int temp1;
temp0 = *(p + 0);
temp1 = *(p + 1);
for(int n = 0 ;n < 27 ; n++)
{
*(p + n ) = *(p + n + 2);
}
*(p +26) = temp0;
*(p +27) = temp1;
} }
/*=========================x_or异或运算============================*/ void x_or(int *p1,int *p2,int num)//num为数组内的数据个数
{
int temp = 0;
for(int i = 0; i < num; i++)
{
temp = *(p1+i) + *(p2+i);
temp = temp - (temp/2)*2;
*(p1+i) = temp;
} }
/*=======================Dcm_Binary_Swap十进制转为二进制============================*/ void db_swap(int dcm,int *p )
{
int temp1 = dcm;
int temp2;
for(int i = 3;i >= 0;i--)
{
temp2 = temp1/2;
temp1 = temp1 - temp2*2;
*(p+i) = temp1;
temp1 = temp2;
} }
/*==================根据后一次L,R推出前一次L,R====================*/
void getdt1(int E[],int S[][64],int *k,int *L,int *R)//利用后一次LR必要的密码信息,得到上一次的LR
{ int i,j;
int NR[48];
int NDS[32];
int tR[32];
int tL[32];
int h,l,temp;
for(i=0;i<=31;i++)
{
tR[i]=*(L+i);//本轮的左边为上一轮末尾的右边
}
for(i=0;i<=31;i++)
{
tL[i]=*(R+i);//把与L异或运算后的NDS赋值给tL
}
//对R进行加密从而获得“新鲜的(没有和L异或运算的)”NDS
for(i=0;i<=47;i++)
{
NR[i]=tR[E[i]];
}
x_or(NR,k,48);
for(j=0;j<=7;j++)
{
h=NR[0+6*j]*2+NR[5+6*j];
l=NR[1+6*j]*8+NR[2+6*j]*4+NR[3+6*j]*2+NR[4+6*j];
temp=S[j][h*16+l];
db_swap(temp,(NDS+j*4));
}
x_or(tL,NDS,32);//tL(L与NDS异或运算的结果)再次与NDS异或,得到L
for(i=0;i<=31;i++)
{
*(L+i)=tL[i];
}
for(i=0;i<=31;i++)
{
*(R+i)=tR[i];
} }
/*=====================输出函数,把二进制转为char字符==================*/
void showt(int a[])//输出a,0、1数组代表的八个字符
{
char c;
int temp;
int i,j,n;
for(i=0;i<=7;i++)
{
temp=0;
for(j=0;j<=7;j++)
{
temp=temp+a[i*8+j]*(pow(2,(7-j))); //8位二进制转为十进制 }
c=temp;//把temp转为字符型
cout<<c<<endl;
}
} class des2;//加密
class ides;//解密 /*=================================产生16个子秘钥======================================*/ class des//用来产生16个子密钥
{
private:
int K0[56];//最原始的密码,没有奇偶校验位。
int C0[28],D0[28];//第一次将密码分组
int C[16][28],D[16][28];//以后将密码分组
int K[16][48];//最终的密码
int pc2[48];
int I[16];//移位的位数 public:
des();
friend des2;
friend ides; };
des::des()
{
//setI()
int tempI[16]={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
for(int n=0;n<=15;n++)
{
I[n]=tempI[n];
} //setpc2()
int temppc2[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,55,34,53,46,42,50,36,29,32};
for( int n=0;n<=47;n++)
{
pc2[n]=temppc2[n];
} //setK0() int tempK0[56]={1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,
0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0};
for( int n=0;n<=55;n++)
{
K0[n]=tempK0[n];
} //getC0() for( int n=0;n<=27;n++)
{
C0[n]=K0[n];//C0等于K0的前半数据
} //getD0() for( int n=0;n<=27;n++)
{
D0[n]=K0[n+28];//D0等于K0的后半数据
} //getC() int tempC[28];
for( int n=0;n<=27;n++)
{
tempC[n]=C0[n];
}
for(int i=0;i<=15;i++)
{
loop_move(tempC,I[i]);//将C0移位I(i)
for(int n=0;n<=27;n++)
{
C[i][n]=tempC[n];
}
} //getD() int tempD[28];
for(int n=0;n<=27;n++)
{
tempD[n]=D0[n];
}
for(int i=0;i<=15;i++)
{
loop_move(tempD,I[i]);//将D0移位I(i)
for(int n=0;n<=27;n++)
{
D[i][n]=tempD[n];
}
} //getK() int CD[56];
for( int n=0;n<=15;n++)//把C0和D0合起来
{
for( int i=0;i<=27;i++)
{
CD[i]=C[n][i];
}
for(int i=28;i<=55;i++)
{
CD[i]=D[n][i-28];
}
for(int i=0;i<=47;i++)
{
K[n][i]=CD[pc2[i]];
}
}
} /*=======================加密============================*/
//giveM 加密算法
class des2
{
public:
des2();
void giveM(int *p);
private:
char c[8];//原文
int Y0[64];//原文的二进制形式
int IP[64];//IP置换表
int S[8][64];//S盒
int E[48];//扩充表
int IP_1[64];//IP置换表
int L[32];//Y 的左半部分
int R[32];//Y 的右半部分
int NR[48];//用E扩充后的bit
int NDS[32];//S盒压缩后的bit
int Y[64];//被IP置乱后的Y0
int M[64];//密文
int K[16][48];//16个子秘钥
};
des2::des2()
{ int i,j;
int temp1,temp2;
cout<<"输入内容(8个符号):"<<endl;//DES加密以8个字符为一组
for(i=0;i<=7;i++){cin>>c[i];} for(i=0;i<=7;i++)
{
temp1=c[i];//字符转换为int型ASCII,进而转换成二进制
for(j=0;j<=7;j++)//8个十进制数转换为64个二进制bit
{
temp2=temp1/2;
Y0[i*8+7-j]=temp1%2;
temp1=temp2;
}
} //setS() 八个S黑盒的具体内容
int tempS[8][64]={
{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},
};
for(i=0;i<=7;i++)
{
for(j=0;j<=63;j++)
{
S[i][j]=tempS[i][j];
}
} //setE() 用于 32位——>48位 扩充的E置换表 int tempE[48]={0,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,0,1};
for(i=0;i<=47;i++)
{
E[i]=tempE[i];
} //setIP_1() 置换表 int tempIP_1[64]={40,8,48,16,56,24,0,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};
for(i=0;i<=63;i++)
{
IP_1[i]=tempIP_1[i];
} //setIP() 置换表 int tempIP[64]={19,50,42,34,11,18,10,2,60,51,44,36,28,20,12,7,62,54,46,38,30,17,14,6,0,
56,48,40,32,24,16,8,57,49,41,33,25,22,9,1,59,52,43,35,27,58,26,3,61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,4};
for(i=0;i<=63;i++)
{
IP[i]=tempIP[i];
} //getKLR() 获取16个子秘钥 int n; int h,l;
int temp; des jm;//定义“用于产生16个子秘钥的”对象 for(i=0;i<=15;i++)
{
for(j=0;j<=47;j++)
{
K[i][j]=jm.K[i][j];
}
}
//getM() 产生密文
for(i=0;i<=63;i++)
{
Y[i]=Y0[IP[i]];//将原始数据经过IP进行第一次置乱
} for(i=0;i<=31;i++)//Y 的左半部分
{
L[i]=Y[i]; } for(i=0;i<=31;i++)//Y 的右半部分
{
R[i]=Y[i+32]; } for(n=0;n<=15;n++)
{ for(i=0;i<=47;i++)
{
NR[i]=R[E[i]];//用E把R扩充为48位
}
x_or(NR,jm.K[n],48);//用子秘钥K[n]对NR加密(总共加密15轮哦)
for(j=0;j<=7;j++)//S盒压缩处理(6——>4)
{
h=NR[0+6*j]*2+NR[5+6*j];//首位组成十进制数作为表的 行
l=NR[1+6*j]*8+NR[2+6*j]*4+NR[3+6*j]*2+NR[4+6*j];//中间组成十进制数作为表的 列
temp=S[j][h*16+l];//对应的十进制值
db_swap(temp,(NDS+j*4));//把1个十进制数转换为4个二进制bit
} x_or(NDS,L,32);//R被加密为NDS后与L异或运算
for(i=0;i<=31;i++)//R作为下一轮加密的L
{
L[i]=R[i];}
for(i=0;i<=31;i++)//L作为下一轮加密的R
{
R[i]=NDS[i];
}
} //把经过16轮加密后的密文L、R放一块,最后再赋值给M
int tempM[64];
for(i=0;i<=31;i++)
{
tempM[i]=L[i];
}
for(i=32;i<=63;i++)
{
tempM[i]=R[i-32];
}
for(i=0;i<=63;i++)
{
M[i]=tempM[IP_1[i]];
} }
void des2::giveM(int *p)//把密文赋值给传入的地址
{
int i;
for(i=0;i<=63;i++)
{
*(p+i)=M[i];
}
} /*========================================解密=================================*/
class ides
{
public:
int E[48];
int S[8][64];
int IP_1[64];
int IP[64];
int K[16][48];
int A[64]; ides();
void getA(int M[]);
void giveA(int *p);
};
ides::ides()
{
int i,j;
//setE()
int tempE[48]={0,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,0,1};
for(i=0;i<=47;i++)
{
E[i]=tempE[i];
}
//setS()
int tempS[8][64]={{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},
};
for(i=0;i<=7;i++)
{
for(j=0;j<=63;j++)
{
S[i][j]=tempS[i][j];
}
}
//getIP_1
int tempIP_1[64]={40,8,48,16,56,24,0,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};
for(i=0;i<=63;i++)
{
IP_1[i]=tempIP_1[i];
}
//setIP
int tempIP[64]={19,50,42,34,11,18,10,2,60,51,44,36,28,20,12,7,62,54,46,38,30,17,14,6,0,
56,48,40,32,24,16,8,57,49,41,33,25,22,9,1,59,52,43,35,27,58,26,3,61,53,45,37,29,21,13,5,63,55,47,39,31,23,15,4};
for(i=0;i<=63;i++)
{
IP[i]=tempIP[i];
}
//getK
des jm;
for(i=0;i<=15;i++)
{
for(j=0;j<=47;j++)
{
K[i][j]=jm.K[i][j]; } } }
void ides::getA(int M[])
{
int i,j;
int nM[64];
int L[32],R[32];
for(i=0;i<=63;i++)
{
nM[IP_1[i]]=M[i];//还原被IP_1置乱的密文
}
for(i=0;i<=31;i++)
{
L[i]=nM[i];
}
for(j=0;j<=31;j++)
{
R[j]=nM[j+32];
}
int tA[64]; for(i=15;i>=0;i--)
{getdt1(E,S,K[i],L,R);}//还原16轮的加密
cout<<endl;
//把L和R合一块
for(i=0;i<=31;i++)
{
tA[i]=L[i];
}
for(i=32;i<=63;i++)
{
tA[i]=R[i-32];
}
for(i=0;i<=63;i++)
{
A[IP[i]]=tA[i];//还原第一次的置乱,获得原文的二进制ASCII bit
} }
void ides::giveA(int *p)//把原文赋值给*P
{
int i;
for(i=0;i<=63;i++)
{
*(p+i)=A[i];
}
} int main()
{ int miwen[64];
int jimizhihou[64];
des2 jm2;
jm2.giveM(miwen);
cout<<endl;
cout<<"[密文]:"<<endl; showt(miwen); ides am;
am.getA(miwen);
am.giveA(jimizhihou);
cout<<endl;
cout<<"[密文]破解结果:"<<endl;
showt(jimizhihou);
cout<<endl; return 0;
}

DES加密 超详解 及 C++编程实现的更多相关文章

  1. DES加密模式详解

    DES加密模式详解 http://www.cnblogs.com/Lawson/archive/2012/05/20/2510781.html http://www.blogjava.net/wayn ...

  2. JAVA实现DES加密实现详解

    package util; import java.security.SecureRandom; import javax.crypto.spec.DESKeySpec; import javax.c ...

  3. 【Java】JAVA-加密-DES加密代码详解

    package util; import java.security.SecureRandom; import javax.crypto.spec.DESKeySpec; import javax.c ...

  4. html5的float属性超详解(display,position, float)(文本流)

    html5的float属性超详解(display,position, float)(文本流) 一.总结 1.文本流: 2.float和绝对定位都不占文本流的位置 3.普通流是默认定位方式,就是依次按照 ...

  5. HTML中DOM核心知识有哪些(带实例超详解)

    HTML中DOM核心知识有哪些(带实例超详解) 一.总结: 1.先取html元素,然后再对他进行操作,取的话可以getElementById等 2.操作的话,可以是innerHtml,value等等 ...

  6. Mysql超详解

    Mysql超详解 一.命令框基本操作及连接Mysql 找到Mysql安装路径,查看版本 同时按快捷键win+R会弹出一个框,在框中输入cmd 点击确定后会出现一个黑框,这是命令框,我们的操作要在这命令 ...

  7. Mybatis案例超详解(上)

    Mybatis案例超详解(上) 前言: 本来是想像之前一样继续跟新Mybatis,但由于种种原因,迟迟没有更新,快开学了,学了一个暑假,博客也更新了不少,我觉得我得缓缓,先整合一些案例练练,等我再成熟 ...

  8. 开源项目SMSS发开指南(五)——SSL/TLS加密通信详解(下)

    继上一篇介绍如何在多种语言之间使用SSL加密通信,今天我们关注Java端的证书创建以及支持SSL的NioSocket服务端开发.完整源码 一.创建keystore文件 网上大多数是通过jdk命令创建秘 ...

  9. Python3调用C程序(超详解)

    Python3调用C程序(超详解) Python为什么要调用C? 1.要提高代码的运算速度,C比Python快50倍以上 2.对于C语言里很多传统类库,不想用Python重写,想对从内存到文件接口这样 ...

随机推荐

  1. JavaWeb 补充(Json)

    HTML DOM alert() 方法 定义和用法 alert() 方法用于显示带有一条指定消息和一个 OK 按钮的警告框. 参数 描述 message 要在 window 上弹出的对话框中显示的纯文 ...

  2. Vue学习笔记(三)

    1 监听 在Vue.js中可以通过watch来监听数据的变化,比如通过watch实现的简单计数器: <div id="app"> <p>计数器:{{coun ...

  3. 0802_转载-nn模块中的网络层介绍

    0802_转载-nn 模块中的网络层介绍 目录 一.写在前面 二.卷积运算与卷积层 2.1 1d 2d 3d 卷积示意 2.2 nn.Conv2d 2.3 转置卷积 三.池化层 四.线性层 五.激活函 ...

  4. JAVAEE_01_什么是javaEE

    javaEE Java平台包含三个版本: - JavaME :适用于小型设备和智能卡的JavaME (Java Platform Micro Edition,Java微型版) - JavaSE : 适 ...

  5. Java整合极光推送 ( 简单 )

    Java 整合极光推送官方文档:https://github.com/jpush/jpush-api-java-client 这里记录一下简单的使用步骤:创建一个普通的 Maven 工程然后添加依赖 ...

  6. 深入探索Android热修复技术原理读书笔记 —— 热修复技术介绍

    1.1 什么是热修复 对于广大的移动开发者而言,发版更新是最为寻常不过的事了.然而,如果你 发现刚发出去的包有紧急的BUG需要修复,那你就必须需要经过下面这样的流程: 这就是传统的更新流程,步骤十分繁 ...

  7. shopify 学习链接整理

    shopify shopify packagist https://help.shopify.com/zh-CN/manual/apps/apps-by-shopify/script-editor/s ...

  8. Social engineering tookit 钓鱼网站

    目录 Set 钓鱼攻击 网站克隆 Set Set(Social engineering tookit)是一款社会工程学工具,该工具用的最多的就是用来制作钓鱼网站. Kali中自带了该工具. 钓鱼攻击 ...

  9. MySQL UDF提权执行系统命令

    目录 UDF UDF提权步骤 UDF提权复现(php环境) UDF UDF (user defined function),即用户自定义函数.是通过添加新函数,对MySQL的功能进行扩充,其实就像使用 ...

  10. ExtJS4中Ext.onReady、Ext.define、Ext.create

    1.Ext.onReady 说明:onReady内的语句块会在页面上下文加载后再执行. 2.Ext.define 说明:创建类,可以继承其他类,也可以被继承. 例子1: 1 <script ty ...