• 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 的?

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

    可以发现扩展置换表有重复部分,这样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;
    }
    
    
    
  • 相关阅读:
    ensp上防火墙上配置nat
    简单介绍oracle误删除表和表数据的恢复方法
    linux基本命令介绍(二)
    linux基本命令介绍(一)
    Vsan分布式文件系统逻辑架构损坏恢复过程
    iPhone手机硬件拆解介绍
    硬盘分区损坏导致SqlServer数据丢失怎么恢复
    安卓手机密码工作原理及破解方式
    EMC UNITY 400存储卷删除数据恢复案例
    服务器2块硬盘掉线的数据恢复过程分享
  • 原文地址:https://www.cnblogs.com/hugboy/p/12974393.html
Copyright © 2020-2023  润新知