DES加密 超详解 及 C++编程实现

参考资料:
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 的?

我们来看看扩展置换表和普通置换表的差别
DES加密 超详解 及 C++编程实现
可以发现扩展置换表有重复部分,这样R中就会有部分数据被重复使用,从而达到扩展的效果

那么被重复使用的部分是随意选的吗,它有什么规律呢吗?
DES加密 超详解 及 C++编程实现
由图可知他是把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盒就是一张数据表
DES加密 超详解 及 C++编程实现

对,长的就是这么丑
原来,
6位数的首尾两位组成了一个十进制数,作为表的 行
6位数的中间四位组成一个十进制数,作为表的 列
由行和列在表中可以确定一个值,把该值转换为4位二进制数

DES加密 超详解 及 C++编程实现

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。

运行效果

DES加密 超详解 及 C++编程实现

源码及解析

#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;
}


原文链接: https://www.cnblogs.com/hugboy/p/12974393.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    DES加密 超详解 及 C++编程实现

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/197924

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午7:43
下一篇 2023年2月12日 下午7:43

相关推荐