DES加密 超详解 及 C++编程实现
阅读原文时间:2023年07月11日阅读:2

参考资料:

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轮加密!

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

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

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

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

什么是异或运算呢?

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异或运算也是同样的道理。

  • 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个子密钥

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