zoukankan      html  css  js  c++  java
  • DES算法

    python3可直接调用pyDes库,这里不做详细介绍

    下载及简介地址:https://twhiteman.netfirms.com/des.html

    如需要在python中使用des加密,可以直接使用pyDes库加密,该库提供了CBC和ECB两种加密方式。

    下面是C语言编写的DES算法,没有VC++6.0的同学点这安装

    1、熟悉和掌握对称加密算法的原理及其一般过程;

    2、掌握对称加密算法的基本方法:DES;

    3、掌握使用一定的编码开发工具(对具体的开发平台和工具不作要求)。

     

    VC++6.0

    第一步第一步:变换明文。对给定的64位比特的明文x,首先通过一个置换   IP表来重新排列x,从而构造出64位比特的x0x0=IP(x)=L0R0,其中L0表示x0的前32比特,R0表示x0的后32位。

     

          第二步:按照规则迭代。规则为

    Li = Ri-1

    Ri = Lif(Ri-1,Ki)   i=1,2,3…16

                 经过第一步变换已经得到L0R0的值,其中符号表示的数学运算是异或,f表示一种置换,由S盒置换构成,Ki是一些由密钥编排函数产生的比特块。fKi将在后面介绍。

     

    第三步:对L16R16利用IP-1作逆置换,就得到了密文y

     

    16轮循环:DES对经过初始置换的64位明文进行16轮类似的子加密过程。每一轮的子加密过程要经过DES的f函数,其过程如下:

         将64位明文在中间分开,划分为2部分,每部分32位,左半部分记为L,右半部分记为R,以下的操作都是对右半部分数据进行的。

          扩展置换:扩展置换将32位的输入数据根据扩展置换表扩展成为48位的输出数据。

          异或运算:将48位的明文数据与48位的子密钥进行异或运算(48位子密钥的产生过程在实验原理八.子密钥产生过程中有详细讨论)。

          S盒置换:S盒置换是非线性的,48位输入数据根据S盒置换表置换成为32位输出数据。

          直接置换:S盒置换后的32位输出数据根据直接置换表进行直接置换。

          经过直接置换的32位输出数据与本轮的L部分进行异或操作,结果作为下一轮子加密过程的R部分。本轮的R部分直接作为下一轮子加密过程的L部分。然后进入下一轮子加密过程,直到16轮全部完成。

     

    DES,一种对称加密算法,算法运算速度快,资源消耗较少;但是安全性低。

     

    在DES密钥Key的使用、管理及密钥更换的过程中,应绝对避开DES算法的应用误区,即绝对不能把Key的第8,16,24,…,64位作为有效数据位来对Key进行管理,这一点,对应用DES加密的用户来说要高度重视。

     

    有些网络,利用定期更换DES密钥Key的办法来进一步提高系统的安全性和可靠性,如果忽略了上述应用误区,那么,更换新密钥将是徒劳的,对网络的安全运行将十分危险,所以更换密钥一定要保证新Key与旧Key真正的不同,即除了第8,16,24,…,64位以外其他位数据发生了变化,这一点是非常重要的。 

     

     

     

    附录

    #include<stdio.h>

     

    /*各种函数定义*/

    int move_num(int r);

    void xor(int *r_b, int *k3, int large);

    void s_box(int r_t[32], int r_b[48]);

    void erzhuanshiliu(int *k, char *key, int large);

    void shizhuaner(int *k, int n, int i, int large);

    void round(int r, int k2[56], int k3[48], int r_s[32], int r_b[48], int l[32], int k_c_two[48], int m_c_two[32], int e[48], char c_r[8], char c_l[8]);

    void exchange(int *k1, int *k2, int *rule, int n);

    void key_move(int k2[56], int n);

     

    /*十进制转换成二进制*/

    void shizhuaner(int *k, int n, int i,int large) 

    /* k是存放二进制的数组,n是需要进行转换的十进制数,i是第i个十进制数,large是数组大小*/

    {

           int j;      //计数的j,没什么大的含义

           large = large / 8;

           j = large - 1;

           do

           {

                  k[i * large + j] = n % 2;

                  n = n / 2;

                  j--;

           } while (n != 0);

           while (j >= 0)

           {

                  k[i * large + j] = 0;

                  j--;

           }

           return ;

    }

     

    /*二进制转换成十六进制*/

    void erzhuanshiliu(int *k,char *key, int large)

    /* k是二进制数组,key是存放十六进制的数组,largek数组的大小*/

    {

           int i,j; //计数的ij,没什么大的含义

           large = large / 4;

           for (i = 0; i < large; i++)

           {

                  j = k[i * 4] * 8 + k[i * 4 + 1] * 4 + k[i * 4 + 2] * 2 + k[i * 4 + 3];

                  if (j >= 10)

                  {

                         switch (j)

                         {

                         case 10:key[i] = 'a'; break;

                         case 11:key[i] = 'b'; break;

                         case 12:key[i] = 'c'; break;

                         case 13:key[i] = 'd'; break;

                         case 14:key[i] = 'e'; break;

                         case 15:key[i] = 'f'; break;

                         }

                  }

                  else

                  {

                         j = j + 48;

                         key[i] = (char)j;

                  }

           }

           return;

    }

     

    /*循环函数*/

    void round(int r, int k2[56], int k3[48], int r_s[32], int r_b[48], int l[32], int k_c_two[48], int m_c_two[32], int e[48], char c_r[8], char c_l[8])

    /* r是轮数*/

    /* k2是密钥经过置换1置换完的数组,k3是密钥经过置换2置换完的数组*/

    /* r_s是明文处理中R32大小时的数组,r_b是明文处理中R48大小时的数组,l是明文处理中L的数组*/

    /* k_c_two是密钥处理中置换2的置换规则数组,m_c_two是明文处理中置换2的置换规则数组,e是明文处理中e盒的置换规则数组*/

    /* c_r是各轮密文的r部分,c_l是各轮密文的l部分*/

    {

           int i, n, r_t[32],r_c[32]; //计数的i,没什么大的含义;n存储该轮左移的数值;r_t,r_c存放中间处理数值的32大小的数组

           printf("这是第%d轮密文: ", r);

           n = move_num(r); //获取第r轮密钥左移的位数

           key_move(k2, n); //调用密钥左移函数

           exchange(k2, k3, k_c_two, 48);  //密钥进行置换2运算

           exchange(r_s, r_b,e,48);  //明文进行e盒扩展置换运算

           xor(r_b, k3,48);  //经过密钥置换2运算后的子密钥与从e盒出来的子明文异或 

           s_box(r_t,r_b);  //调用明文处理中的s盒运算函数

           exchange(r_t, r_c, m_c_two, 32);  //明文进行置换2运算

           for (i = 0; i < 32; i++)

                  r_t[i] = r_c[i];

           xor(r_t, l, 32);     //经过处理后的RL异或

           for (i = 0; i < 32; i++)

                  l[i] = r_s[i];  //准备下次循环的L

        for (i = 0; i < 32; i++)

                  r_s[i] = r_t[i];  //准备下次循环的R

           erzhuanshiliu(r_s, c_r, 32);

           for (i = 0; i < 8; i++)

                  printf("%c ", c_r[i]);  //rR部分的密文

           erzhuanshiliu(l, c_l, 32);

           for (i = 0; i < 8; i++)

                  printf("%c ", c_l[i]);  //rL部分的密文

           printf(" ");

           printf(" ");

           return;

    }

     

     

    /* 异或函数 */

    void xor(int *r_b, int *k3,int large)

    {

           int i;  //计数的i,没什么大的含义

           for (i = 0; i < large; i++)

           {

                  if (r_b[i] != k3[i])  //两数相同结果取0,两数不同取1

                         r_b[i] = 1;

                  else

                         r_b[i] = 0;

           }

    }

     

    /* S盒运算函数 */

    void s_box(int r_t[32],int r_b[48])

    {

           int i,hang,lie,jie;  //计数的i,没什么大的含义;hangS盒的行下标;lieS盒的列下标;jie是根据行、列下标查询出的结果

           /* S1~S8 */

           int s1[4][16] = { { 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[4][16] = { { 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[4][16] = { { 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[4][16] = { { 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, 3 },

                             { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } },

               s5[4][16] = { { 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[4][16] = { { 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][16] = { { 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[4][16] = { { 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 < 8; i++)

           {

                  hang = r_b[i * 6] * 2 + r_b[i * 6 + 5];  //0位与第5位决定行下标

                  lie = r_b[i * 6 + 1] * 8 + r_b[i * 6 + 2] * 4 + r_b[i * 6 + 3] * 2 + r_b[i * 6 + 4];  //1234位决定列下标

                  switch (i)  //i个数查询Si

                  {

                  case 0:jie = s1[hang][lie]; break;

                  case 1:jie = s2[hang][lie]; break;

                  case 2:jie = s3[hang][lie]; break;

                  case 3:jie = s4[hang][lie]; break;

                  case 4:jie = s5[hang][lie]; break;

                  case 5:jie = s6[hang][lie]; break;

                  case 6:jie = s7[hang][lie]; break;

                  case 7:jie = s8[hang][lie]; break;

                  }

                  shizhuaner(r_t, jie, i,32);  //S盒为十六进制,须转换回二进制进行存放

           }

    }

     

    /*左移函数*/

    void key_move(int k2[56], int n)

    {

           int i, one, two, twentyeight, twentynight;  //计数的i,没什么大的含义;onetwotwentyeighttwentynight用于存放第122829个数

           one = k2[0];  //先记录第122829个数

           two = k2[1];

           twentyeight = k2[28];

           twentynight = k2[29];

           for (i = 0; i < (28 - n); i++)  //循环赋值

           {

                  k2[i] = k2[i + n];

                  k2[i + 28] = k2[i + n + 28];

           }

           if (n == 1)  //左移1位时,特殊端点值(第2755)赋值

           {

                  k2[27] = one;

                  k2[55] = twentyeight;

           }

           else  //左移2位时,特殊端点值(第27285455)赋值

           {

                  k2[26] = one;

                  k2[27] = two;

                  k2[54] = twentyeight;

                  k2[55] = twentynight;

           }     

    }

     

    /* 获取第r轮左移位数 */

    int move_num(int r)

    {

           int i;  //i存储移动的位数

           switch (r)

           {

           case 1:i = 1; break;

           case 2:i = 1; break;

           case 3:i = 2; break;

           case 4:i = 2; break;

           case 5:i = 2; break;

           case 6:i = 2; break;

           case 7:i = 2; break;

           case 8:i = 2; break;

           case 9:i = 1; break;

           case 10:i = 2; break;

           case 11:i = 2; break;

           case 12:i = 2; break;

           case 13:i = 2; break;

           case 14:i = 2; break;

           case 15:i = 2; break;

           case 16:i = 1; break;

           }

           return i;  //返回移动的位数

    }

     

    /* 置换函数 */

    void exchange(int *k1, int *k2, int *rule,int n)

    {

           int i, j;  //计数的ij

           for (i = 0; i < n; i++)

           {

                  j = rule[i];     //根据rule数组进行置换,也就是赋值

                  k2[i] = k1[j-1];

           }

           return;

    }

     

    /*主函数*/

    int main()

    {

           /* c是最终密文,c_r是密文的R部分,c_l是密文的L的部分,g是用于缓冲掉回车符,k接收从键盘输入密钥,m接收从键盘输入的明文*/

           char c[16],c_r[8],c_l[8], g, k[8], m[8];

           /* 计数的ijr是轮数;n接收类型转换后的结果;k1k2k3是密钥处理中不同大小的数组;m1m2是明文处理中的数组,r_sR 32大小时的数组,r_bR 48大小时的数组,lL的数组*/

           int i, j, r, n, k1[64], k2[56], k3[48], m1[64], m2[64],r_s[32],r_b[48],l[32];

           /* k_c_one是密钥处理的置换1k_c_two是密钥处理的置换2m_c_one是明文处理的置换1e是明文处理的e盒,m_c_two是明文处理的置换2 */

           int k_c_one[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 },

                  k_c_two[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 },

                  m_c_one[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 },

                  e[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 },

                  m_c_two[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 },

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

           printf("******DES加密****** ");

           printf(" ");

           printf("请输入加密的密钥: ");

           for (i = 0; i < 8; i++)  //从键盘里获取输入的密钥

           {

                  scanf("%c", &k[i]);

                  n = (int)k[i];

                  shizhuaner(k1, n, i,64);  //进行密钥进制转换

           }

           g = getchar();  //缓冲掉多于8个字符以外字符和回车符

           while (g != ' ')

           {

                  g = getchar();

           }

           printf("请输入需要加密的明文: ");

           for (i = 0; i < 8; i++)  //从键盘里获取输入的明文

           {

                  scanf("%c", &m[i]);

                  n = (int)m[i];

                  shizhuaner(m1, n, i,64);  //进行明文进制转换

           }

           g = getchar();  //缓冲掉多于8个字符以外字符和回车符

           while (g != ' ')

           {

                  g = getchar();

           }

           printf(" ");

           exchange(k1, k2, k_c_one, 56);  //密钥进行置换1处理

           exchange(m1, m2, m_c_one, 64);  //明文进行密钥1处理

           for (i = 0; i < 32; i++)

                  l[i] = m2[i];  //明文的L部分

           j = 0;

           for (i = 32; i < 64; i++)

           {

                  r_s[j] = m2[i];  //明文的R部分

                  j++;

           }     

           for (r = 1; r <= 16; r++)  //进行16轮的循环处理

                  round(r,k2, k3, r_s, r_b, l, k_c_two, m_c_two, e,  c_r, c_l);

           for (i = 0; i < 64; i++)  //将密文R的部分与密文L的部分合一起

           {

                  m1[i] = r_s[i];

                  if (i >= 32)

                         m1[i] = l[i - 32];

           }

           exchange(m1, m2, m_c_three, 64);  //进行明文处理的置换3

           erzhuanshiliu(m2, c, 64);  //二进制转换成十六进制,得到最终密文

           printf("这是最终密文: ");

           for (i = 0; i < 16; i++)

                  printf("%c ", c[i]);

           printf(" ");

           return 0;

    }

  • 相关阅读:
    021.day21 反射 Class类 反射常用操作
    020.day20 线程概述 多线程优缺点 线程的创建 线程常用方法 生命周期 多线程同步
    019.day19 缓冲流 对象流 标准输入输出流
    018.day18 map集合如何实现排序 File类 IO流 字节流 字符流 编码
    017.day17 Map接口 克隆 treeSet集合排重缺陷
    016.day16 HashSet TreeSet 比较器Comparable Comparator
    015.day15
    014.day14
    013.day13
    线程
  • 原文地址:https://www.cnblogs.com/WhiteHatKevil/p/10095208.html
Copyright © 2011-2022 走看看