DES加密算法—实现(C语言)

2023-05-16

http://www.iteye.com/topic/478024

DES(Data Encrypt Standard数据库加密标准)是迄今为止使用最广泛的加密体制。

     初学信息安全的新生,一般都会被老师要求实现DES算法,如果老师不要求,那么有缘来我这里共同学习的朋友,我建议你用C去实现一下,C语言在信息安全领域很重要,更何况隶属于工科的信息安全,你只懂理论是远远不够的。

     想用其他语言实现的朋友,如果你用了汇编,那么请您老人家走开不要来看小弟的笑话。如果你用C++或者JAVA,那么我劝您用C吧,因为2年前本人计算过速度,在我的机器上,同样的代码,用C++新建的工程要比用C新建的工程慢了2倍。至于JAVA,我估计要慢10倍。

     废话不多说,DES算法的理论我就不聒噪了,想要了解其实现的人,如果不懂其理论就来看这文章,即便是看懂了也会走火入魔,或者是某位学生心怀不轨。

    

     一个加密算法的实现,最最重要的关键词是—速度。

     举个例子来说明,速度对加密算法的重要:假设我们实现了两个加密算法DES1.0和DES2.0,其中DES1.0的速度为900KB/S,DES2.0的速度为1000KB/S。假设一个文件有10G,我需要对其进行加密,那么,用DES1.0所耗费的时间为1111s,DES2.0的速度为1000S。DES2.0比DES1.0快了111秒。现实生活里我们要加密的数据还可能远远不止10G。

不要小看这111S,要知道,让CPU尽可能的为用户服务,是我们每一个程序员的职责,不论你是用C,C++还是JAVA。

     因此,为了速度,我们必须舍弃一些东西。

     有的同学喜欢用动态数组,因为这也是个好东西,可以节约空间,于是有人认为用了动态数组的程序比不用动态数组的程序要高了好几级。

     动态数组貌似高深,但如果你用在加密算法里,我只能说这位同学啊你真是吃力不讨好,在计算机世界里,往往静态的东西就是比动态的东西速度要快。

     在此我首先声明,如果你不是在练习结构体和malloc/calloc的使用,那么请你果断舍弃这些在加密算法里华而不实的东西。

     好了,说了这么多,各位看官都等急了吧,下面我就结合DES算法原理来分步骤讲解我的代码。 

    一、准备

    首先,头文件与宏定义。

C代码   收藏代码
  1. #include "stdio.h"  
  2. #include "memory.h"  
  3. #include "time.h"  
  4. #include "stdlib.h"  
  5.   
  6. #define PLAIN_FILE_OPEN_ERROR -1  
  7. #define KEY_FILE_OPEN_ERROR -2  
  8. #define CIPHER_FILE_OPEN_ERROR -3  
  9. #define OK 1      

    其次,对基本数据类型进行typedef。

    这句是不可以少的,请养成良好习惯,不然以后如果你要修改基本数据类型,累死你。   

C代码   收藏代码
  1. typedef char ElemType;  

   

    而后,是初始置换表,逆初始置换表,S-Box等已知数据。    

C代码   收藏代码
  1.  //初始置换表IP  
  2. int IP_Table[64] = {  57,49,41,33,25,17,9,1,  
  3.                                  59,51,43,35,27,19,11,3,  
  4.                                  61,53,45,37,29,21,13,5,  
  5.                                  63,55,47,39,31,23,15,7,  
  6.                                  56,48,40,32,24,16,8,0,  
  7.                                  58,50,42,34,26,18,10,2,  
  8.                                  60,52,44,36,28,20,12,4,  
  9.                                  62,54,46,38,30,22,14,6};   
  10. //逆初始置换表IP^-1  
  11. int IP_1_Table[64] = {39,7,47,15,55,23,63,31,  
  12.            38,6,46,14,54,22,62,30,  
  13.            37,5,45,13,53,21,61,29,  
  14.            36,4,44,12,52,20,60,28,  
  15.            35,3,43,11,51,19,59,27,  
  16.            34,2,42,10,50,18,58,26,  
  17.            33,1,41,9,49,17,57,25,  
  18.            32,0,40,8,48,16,56,24};  
  19.   
  20. //扩充置换表E  
  21. int E_Table[48] = {31, 0, 1, 2, 3, 4,  
  22.                   3,  4, 5, 6, 7, 8,  
  23.                   7,  8,9,10,11,12,  
  24.                   11,12,13,14,15,16,  
  25.                   15,16,17,18,19,20,  
  26.                   19,20,21,22,23,24,  
  27.                   23,24,25,26,27,28,  
  28.                   27,28,29,30,31, 0};  
  29.   
  30. //置换函数P  
  31. int P_Table[32] = {15,6,19,20,28,11,27,16,  
  32.                   0,14,22,25,4,17,30,9,  
  33.                   1,7,23,13,31,26,2,8,  
  34.                   18,12,29,5,21,10,3,24};  
  35.   
  36. //S盒  
  37. int S[8][4][16] =//S1  
  38.             {{{14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7},  
  39.               {0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8},  
  40.                 {4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0},  
  41.                 {15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13}},  
  42.                 //S2  
  43.               {{15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10},  
  44.               {3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5},  
  45.               {0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15},  
  46.               {13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9}},  
  47.               //S3  
  48.               {{10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8},  
  49.               {13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1},  
  50.                 {13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7},  
  51.               {1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12}},  
  52.               //S4  
  53.               {{7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15},  
  54.               {13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9},  
  55.               {10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4},  
  56.               {3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14}},  
  57.               //S5  
  58.               {{2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9},  
  59.               {14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6},  
  60.               {4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14},  
  61.               {11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3}},  
  62.               //S6  
  63.               {{12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11},  
  64.               {10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8},  
  65.               {9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6},  
  66.               {4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13}},  
  67.               //S7  
  68.               {{4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1},  
  69.               {13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6},  
  70.               {1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2},  
  71.               {6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}},  
  72.               //S8  
  73.               {{13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7},  
  74.               {1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2},  
  75.               {7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8},  
  76.               {2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}}};  
  77. //置换选择1  
  78. int PC_1[56] = {56,48,40,32,24,16,8,  
  79.               0,57,49,41,33,25,17,  
  80.               9,1,58,50,42,34,26,  
  81.               18,10,2,59,51,43,35,  
  82.               62,54,46,38,30,22,14,  
  83.               6,61,53,45,37,29,21,  
  84.               13,5,60,52,44,36,28,  
  85.               20,12,4,27,19,11,3};  
  86.   
  87. //置换选择2  
  88. int PC_2[48] = {13,16,10,23,0,4,2,27,  
  89.               14,5,20,9,22,18,11,3,  
  90.               25,7,15,6,26,19,12,1,  
  91.               40,51,30,36,46,54,29,39,  
  92.               50,44,32,46,43,48,38,55,  
  93.               33,52,45,41,49,35,28,31};  
  94.   
  95. //对左移次数的规定  
  96. int MOVE_TIMES[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};  

    二、模块化。

    对面向过程的程序,模块化是否清晰是至关重要的。   

    下面是函数的声明:

C代码   收藏代码
  1. int ByteToBit(ElemType ch,ElemType bit[8]);  
  2. int BitToByte(ElemType bit[8],ElemType *ch);  
  3. int Char8ToBit64(ElemType ch[8],ElemType bit[64]);  
  4. int Bit64ToChar8(ElemType bit[64],ElemType ch[8]);  
  5. int DES_MakeSubKeys(ElemType key[64],ElemType subKeys[16][48]);  
  6. int DES_PC1_Transform(ElemType key[64], ElemType tempbts[56]);  
  7. int DES_PC2_Transform(ElemType key[56], ElemType tempbts[48]);  
  8. int DES_ROL(ElemType data[56], int time);  
  9. int DES_IP_Transform(ElemType data[64]);  
  10. int DES_IP_1_Transform(ElemType data[64]);  
  11. int DES_E_Transform(ElemType data[48]);  
  12. int DES_P_Transform(ElemType data[32]);  
  13. int DES_SBOX(ElemType data[48]);  
  14. int DES_XOR(ElemType R[48], ElemType L[48],int count);  
  15. int DES_Swap(ElemType left[32],ElemType right[32]);  
  16. int DES_EncryptBlock(ElemType plainBlock[8], ElemType subKeys[16][48], ElemType cipherBlock[8]);  
  17. int DES_DecryptBlock(ElemType cipherBlock[8], ElemType subKeys[16][48], ElemType plainBlock[8]);  
  18. int DES_Encrypt(char *plainFile, char *keyStr,char *cipherFile);  
  19. int DES_Decrypt(char *cipherFile, char *keyStr,char *plainFile);  

    其实,模块化与速度也是一对矛盾,因为了解函数运行机制的人就知道,我们的计算机在运行某个函数时,是要用栈来保存入口状态的,在运行结束后又要恢复现场,这些操作势必会影像系统性能,但我们不能将所有代码写在Main函数里,虽然那样做我们的加密算法效率又会大增,但是那种代码未免太过于丑陋不堪。因此,为了帅,还是牺牲一下性能吧。

    三、实现。

    代码里能用移位操作都尽量用了移位操作,能用逻辑运算符的都用了逻辑运算符。

    详细的行注相信你可以看懂吧。有问题可以M我。

C代码   收藏代码
  1. //字节转换成二进制  
  2. int ByteToBit(ElemType ch, ElemType bit[8]){  
  3.     int cnt;  
  4.     for(cnt = 0;cnt < 8; cnt++){  
  5.         *(bit+cnt) = (ch>>cnt)&1;  
  6.     }  
  7.     return 0;  
  8. }  
  9.   
  10. //二进制转换成字节  
  11. int BitToByte(ElemType bit[8],ElemType *ch){  
  12.     int cnt;  
  13.     for(cnt = 0;cnt < 8; cnt++){  
  14.         *ch |= *(bit + cnt)<<cnt;  
  15.     }  
  16.     return 0;  
  17. }  
  18.   
  19. //将长度为8的字符串转为二进制位串  
  20. int Char8ToBit64(ElemType ch[8],ElemType bit[64]){  
  21.     int cnt;  
  22.     for(cnt = 0; cnt < 8; cnt++){          
  23.         ByteToBit(*(ch+cnt),bit+(cnt<<3));  
  24.     }  
  25.     return 0;  
  26. }  
  27.   
  28. //将二进制位串转为长度为8的字符串  
  29. int Bit64ToChar8(ElemType bit[64],ElemType ch[8]){  
  30.     int cnt;  
  31.     memset(ch,0,8);  
  32.     for(cnt = 0; cnt < 8; cnt++){  
  33.         BitToByte(bit+(cnt<<3),ch+cnt);  
  34.     }  
  35.     return 0;  
  36. }  
  37.   
  38. //生成子密钥  
  39. int DES_MakeSubKeys(ElemType key[64],ElemType subKeys[16][48]){  
  40.     ElemType temp[56];  
  41.     int cnt;  
  42.     DES_PC1_Transform(key,temp);//PC1置换  
  43.     for(cnt = 0; cnt < 16; cnt++){//16轮跌代,产生16个子密钥  
  44.         DES_ROL(temp,MOVE_TIMES[cnt]);//循环左移  
  45.         DES_PC2_Transform(temp,subKeys[cnt]);//PC2置换,产生子密钥  
  46.     }  
  47.     return 0;  
  48. }  
  49.   
  50. //密钥置换1  
  51. int DES_PC1_Transform(ElemType key[64], ElemType tempbts[56]){  
  52.     int cnt;      
  53.     for(cnt = 0; cnt < 56; cnt++){  
  54.         tempbts[cnt] = key[PC_1[cnt]];  
  55.     }  
  56.     return 0;  
  57. }  
  58.   
  59. //密钥置换2  
  60. int DES_PC2_Transform(ElemType key[56], ElemType tempbts[48]){  
  61.     int cnt;  
  62.     for(cnt = 0; cnt < 48; cnt++){  
  63.         tempbts[cnt] = key[PC_2[cnt]];  
  64.     }  
  65.     return 0;  
  66. }  
  67.   
  68. //循环左移  
  69. int DES_ROL(ElemType data[56], int time){     
  70.     ElemType temp[56];  
  71.   
  72.     //保存将要循环移动到右边的位  
  73.     memcpy(temp,data,time);  
  74.     memcpy(temp+time,data+28,time);  
  75.       
  76.     //前28位移动  
  77.     memcpy(data,data+time,28-time);  
  78.     memcpy(data+28-time,temp,time);  
  79.   
  80.     //后28位移动  
  81.     memcpy(data+28,data+28+time,28-time);  
  82.     memcpy(data+56-time,temp+time,time);      
  83.   
  84.     return 0;  
  85. }  
  86.   
  87. //IP置换  
  88. int DES_IP_Transform(ElemType data[64]){  
  89.     int cnt;  
  90.     ElemType temp[64];  
  91.     for(cnt = 0; cnt < 64; cnt++){  
  92.         temp[cnt] = data[IP_Table[cnt]];  
  93.     }  
  94.     memcpy(data,temp,64);  
  95.     return 0;  
  96. }  
  97.   
  98. //IP逆置换  
  99. int DES_IP_1_Transform(ElemType data[64]){  
  100.     int cnt;  
  101.     ElemType temp[64];  
  102.     for(cnt = 0; cnt < 64; cnt++){  
  103.         temp[cnt] = data[IP_1_Table[cnt]];  
  104.     }  
  105.     memcpy(data,temp,64);  
  106.     return 0;  
  107. }  
  108.   
  109. //扩展置换  
  110. int DES_E_Transform(ElemType data[48]){  
  111.     int cnt;  
  112.     ElemType temp[48];  
  113.     for(cnt = 0; cnt < 48; cnt++){  
  114.         temp[cnt] = data[E_Table[cnt]];  
  115.     }     
  116.     memcpy(data,temp,48);  
  117.     return 0;  
  118. }  
  119.   
  120. //P置换  
  121. int DES_P_Transform(ElemType data[32]){  
  122.     int cnt;  
  123.     ElemType temp[32];  
  124.     for(cnt = 0; cnt < 32; cnt++){  
  125.         temp[cnt] = data[P_Table[cnt]];  
  126.     }     
  127.     memcpy(data,temp,32);  
  128.     return 0;  
  129. }  
  130.   
  131. //异或  
  132. int DES_XOR(ElemType R[48], ElemType L[48] ,int count){  
  133.     int cnt;  
  134.     for(cnt = 0; cnt < count; cnt++){  
  135.         R[cnt] ^= L[cnt];  
  136.     }  
  137.     return 0;  
  138. }  
  139.   
  140. //S盒置换  
  141. int DES_SBOX(ElemType data[48]){  
  142.     int cnt;  
  143.     int line,row,output;  
  144.     int cur1,cur2;  
  145.     for(cnt = 0; cnt < 8; cnt++){  
  146.         cur1 = cnt*6;  
  147.         cur2 = cnt<<2;  
  148.           
  149.         //计算在S盒中的行与列  
  150.         line = (data[cur1]<<1) + data[cur1+5];  
  151.         row = (data[cur1+1]<<3) + (data[cur1+2]<<2)  
  152.             + (data[cur1+3]<<1) + data[cur1+4];  
  153.         output = S[cnt][line][row];  
  154.   
  155.         //化为2进制  
  156.         data[cur2] = (output&0X08)>>3;  
  157.         data[cur2+1] = (output&0X04)>>2;  
  158.         data[cur2+2] = (output&0X02)>>1;  
  159.         data[cur2+3] = output&0x01;  
  160.     }     
  161.     return 0;  
  162. }  
  163.   
  164. //交换  
  165. int DES_Swap(ElemType left[32], ElemType right[32]){  
  166.     ElemType temp[32];  
  167.     memcpy(temp,left,32);     
  168.     memcpy(left,right,32);    
  169.     memcpy(right,temp,32);  
  170.     return 0;  
  171. }  
  172.   
  173. //加密单个分组  
  174. int DES_EncryptBlock(ElemType plainBlock[8], ElemType subKeys[16][48], ElemType cipherBlock[8]){  
  175.     ElemType plainBits[64];  
  176.     ElemType copyRight[48];  
  177.     int cnt;  
  178.   
  179.     Char8ToBit64(plainBlock,plainBits);       
  180.     //初始置换(IP置换)  
  181.     DES_IP_Transform(plainBits);  
  182.   
  183.     //16轮迭代  
  184.     for(cnt = 0; cnt < 16; cnt++){         
  185.         memcpy(copyRight,plainBits+32,32);  
  186.         //将右半部分进行扩展置换,从32位扩展到48位  
  187.         DES_E_Transform(copyRight);  
  188.         //将右半部分与子密钥进行异或操作  
  189.         DES_XOR(copyRight,subKeys[cnt],48);   
  190.         //异或结果进入S盒,输出32位结果  
  191.         DES_SBOX(copyRight);  
  192.         //P置换  
  193.         DES_P_Transform(copyRight);  
  194.         //将明文左半部分与右半部分进行异或  
  195.         DES_XOR(plainBits,copyRight,32);  
  196.         if(cnt != 15){  
  197.             //最终完成左右部的交换  
  198.             DES_Swap(plainBits,plainBits+32);  
  199.         }  
  200.     }  
  201.     //逆初始置换(IP^1置换)  
  202.     DES_IP_1_Transform(plainBits);  
  203.     Bit64ToChar8(plainBits,cipherBlock);  
  204.     return 0;  
  205. }  
  206.   
  207. //解密单个分组  
  208. int DES_DecryptBlock(ElemType cipherBlock[8], ElemType subKeys[16][48],ElemType plainBlock[8]){  
  209.     ElemType cipherBits[64];  
  210.     ElemType copyRight[48];  
  211.     int cnt;  
  212.   
  213.     Char8ToBit64(cipherBlock,cipherBits);         
  214.     //初始置换(IP置换)  
  215.     DES_IP_Transform(cipherBits);  
  216.       
  217.     //16轮迭代  
  218.     for(cnt = 15; cnt >= 0; cnt--){        
  219.         memcpy(copyRight,cipherBits+32,32);  
  220.         //将右半部分进行扩展置换,从32位扩展到48位  
  221.         DES_E_Transform(copyRight);  
  222.         //将右半部分与子密钥进行异或操作  
  223.         DES_XOR(copyRight,subKeys[cnt],48);       
  224.         //异或结果进入S盒,输出32位结果  
  225.         DES_SBOX(copyRight);  
  226.         //P置换  
  227.         DES_P_Transform(copyRight);       
  228.         //将明文左半部分与右半部分进行异或  
  229.         DES_XOR(cipherBits,copyRight,32);  
  230.         if(cnt != 0){  
  231.             //最终完成左右部的交换  
  232.             DES_Swap(cipherBits,cipherBits+32);  
  233.         }  
  234.     }  
  235.     //逆初始置换(IP^1置换)  
  236.     DES_IP_1_Transform(cipherBits);  
  237.     Bit64ToChar8(cipherBits,plainBlock);  
  238.     return 0;  
  239. }  
  240.   
  241. //加密文件  
  242. int DES_Encrypt(char *plainFile, char *keyStr,char *cipherFile){  
  243.     FILE *plain,*cipher;  
  244.     int count;  
  245.     ElemType plainBlock[8],cipherBlock[8],keyBlock[8];  
  246.     ElemType bKey[64];  
  247.     ElemType subKeys[16][48];  
  248.     if((plain = fopen(plainFile,"rb")) == NULL){  
  249.         return PLAIN_FILE_OPEN_ERROR;  
  250.     }     
  251.     if((cipher = fopen(cipherFile,"wb")) == NULL){  
  252.         return CIPHER_FILE_OPEN_ERROR;  
  253.     }  
  254.     //设置密钥  
  255.     memcpy(keyBlock,keyStr,8);  
  256.     //将密钥转换为二进制流  
  257.     Char8ToBit64(keyBlock,bKey);  
  258.     //生成子密钥  
  259.     DES_MakeSubKeys(bKey,subKeys);  
  260.       
  261.     while(!feof(plain)){  
  262.         //每次读8个字节,并返回成功读取的字节数  
  263.         if((count = fread(plainBlock,sizeof(char),8,plain)) == 8){  
  264.             DES_EncryptBlock(plainBlock,subKeys,cipherBlock);  
  265.             fwrite(cipherBlock,sizeof(char),8,cipher);    
  266.         }  
  267.     }  
  268.     if(count){  
  269.         //填充  
  270.         memset(plainBlock + count,'\0',7 - count);  
  271.         //最后一个字符保存包括最后一个字符在内的所填充的字符数量  
  272.         plainBlock[7] = 8 - count;  
  273.         DES_EncryptBlock(plainBlock,subKeys,cipherBlock);  
  274.         fwrite(cipherBlock,sizeof(char),8,cipher);  
  275.     }  
  276.     fclose(plain);  
  277.     fclose(cipher);  
  278.     return OK;  
  279. }  
  280.   
  281. //解密文件  
  282. int DES_Decrypt(char *cipherFile, char *keyStr,char *plainFile){  
  283.     FILE *plain, *cipher;  
  284.     int count,times = 0;  
  285.     long fileLen;  
  286.     ElemType plainBlock[8],cipherBlock[8],keyBlock[8];  
  287.     ElemType bKey[64];  
  288.     ElemType subKeys[16][48];  
  289.     if((cipher = fopen(cipherFile,"rb")) == NULL){  
  290.         return CIPHER_FILE_OPEN_ERROR;  
  291.     }  
  292.     if((plain = fopen(plainFile,"wb")) == NULL){  
  293.         return PLAIN_FILE_OPEN_ERROR;  
  294.     }  
  295.   
  296.     //设置密钥  
  297.     memcpy(keyBlock,keyStr,8);  
  298.     //将密钥转换为二进制流  
  299.     Char8ToBit64(keyBlock,bKey);  
  300.     //生成子密钥  
  301.     DES_MakeSubKeys(bKey,subKeys);  
  302.   
  303.     //取文件长度   
  304.     fseek(cipher,0,SEEK_END);   //将文件指针置尾  
  305.     fileLen = ftell(cipher);    //取文件指针当前位置  
  306.     rewind(cipher);             //将文件指针重指向文件头  
  307.     while(1){  
  308.         //密文的字节数一定是8的整数倍  
  309.         fread(cipherBlock,sizeof(char),8,cipher);  
  310.         DES_DecryptBlock(cipherBlock,subKeys,plainBlock);                         
  311.         times += 8;  
  312.         if(times < fileLen){  
  313.             fwrite(plainBlock,sizeof(char),8,plain);  
  314.         }  
  315.         else{  
  316.             break;  
  317.         }  
  318.     }  
  319.     //判断末尾是否被填充  
  320.     if(plainBlock[7] < 8){  
  321.         for(count = 8 - plainBlock[7]; count < 7; count++){  
  322.             if(plainBlock[count] != '\0'){  
  323.                 break;  
  324.             }  
  325.         }  
  326.     }     
  327.     if(count == 7){//有填充  
  328.         fwrite(plainBlock,sizeof(char),8 - plainBlock[7],plain);  
  329.     }  
  330.     else{//无填充  
  331.         fwrite(plainBlock,sizeof(char),8,plain);  
  332.     }  
  333.   
  334.     fclose(plain);  
  335.     fclose(cipher);  
  336.     return OK;  
  337. }  

    最后,写一个简单的main函数来检验它:   

C代码   收藏代码
  1. int main()  
  2. {     
  3.     clock_t a,b;  
  4.     a = clock();  
  5.     DES_Encrypt("1.txt","key.txt","2.txt");  
  6.     b = clock();  
  7.     printf("加密消耗%d毫秒\n",b-a);  
  8.       
  9.     system("pause");  
  10.     a = clock();  
  11.     DES_Decrypt("2.txt","key.txt","3.txt");  
  12.     b = clock();  
  13.     printf("解密消耗%d毫秒\n",b-a);  
  14.     getchar();  
  15.     return 0;  
  16. }   

    运行结果就不重要了,自己去弄几个文件放工程目录下检验去吧。

    至此,整个实现完成。该算法在1.79GHZ的CPU上测试的速度是850KB/S。不过大家别过分在代码上追求速度,做到我以上提到的(舍弃动态内存分配)就足够了,况且,这样做也是在加密算法的程序并不复杂的情况下,如果是一个复杂的系统,那么另当别论,更不必过分到连模块化都不要,那样的代码只会让人觉得丑陋,没人愿意维护。加密算法与CPU的运转速度是成线性关系的。随着双核以及多核CPU的出现,硬件的改善讲会成倍的加快算法的运行速度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DES加密算法—实现(C语言) 的相关文章

随机推荐

  • 按要求编写一个Java应用程序程序: (1)定义一个接口CanFly,描述会飞的方法public void fly(); (2)分别定义类飞机和鸟,实现CanFly接

    代码 第三题 xff1a 按要求编写一个Java应用程序程序 xff1a xff08 1 xff09 定义一个接口CanFly xff0c 描述会飞的方法public void fly xff08 2 xff09 分别定义类飞机和鸟 xff
  • plc热电偶模块模拟量数据波动原因

    要找到模拟数据波动的根本原因 可能是以下原因 您可能使用了自供电或隔离的传感器电源 xff0c 并且两个电源没有相互连接 xff0c 即模拟输入模块的电源接地和传感器的信号接地没有连接 这会产生上下振动的高共模电压 xff0c 从而影响模拟
  • C #Winform窗体自适应

    说明 xff1a Winform让窗体内的控件随着窗体的大小而改变 xff0c 而且能让指定的控件始终处于居中位置 封装成类 xff0c 直接拷贝过去即可 一 类源码如下 xff1a using System using System Co
  • Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)解决方案

    docker service Docker Application Container Engine Loaded loaded usr lib systemd system docker service enabled vendor pr
  • emWin - Movie篇

    STemWin版本 xff1a 544 xff08 ST购买了emWin的license xff0c 可以在ST芯片中使用emWin工具包 xff0c 就叫STemWin xff09 emWin开发工具包可以转换JPG BMP GIF等各种
  • 大规模集群故障处理

    我相信每一个集群管理员 xff0c 在长期管理多个不同体量及应用场景的集群后 xff0c 都会多少产生情绪 其实这在我看来 xff0c 是一个很微妙的事 xff0c 即大家也已经开始人性化的看待每一个集群了 既然是人性化的管理集群 xff0
  • ADRC调试经验(已调通)

    自抗扰控制的组成 有关自抗扰的相关内容 xff0c 韩老师在他的一系列论文中已经描绘的非常清晰了 xff0c 具体资料可以点击这里下载 其中对于TD和ESO这两个部分其实是比较好调节的 xff0c 很容易就能够获得很好的效果 比较难调节的参
  • 浏览器的同源策略

    https developer mozilla org zh CN docs Web Security Same origin policy 这篇翻译不完整 请帮忙从英语翻译这篇文章 同源策略限制了从同一个源加载的文档或脚本如何与来自另一个
  • centos简单解决报错-bash 未找到命令

    centos报错 bash 未找到命令 在使用纯净镜像的时候 经常找不到一些额外的命令 想用但是不知道怎么安装 拿telnet 和netstat 举例 telnet yum provides telnet 这里只需要 yum y span
  • [问题已处理]-docker build出来的镜像没有更新成功

    导语 xff1a 记录一下docker build镜像的坑 如果修改代码文件的话 xff0c docker build 有时候会不替换文件 xff0c 而会使用cache xff0c 导致代码文件没有更新 第一次构建镜像 产生了cache
  • [问题已处理]在docker中使用nohup

    导语 xff1a docker运行容器是否能使用nohup 以下是测试在不同的情况下使用nohup 先启动一个容器 仅看进程的pid号参考 docker run it rm ubuntu 16 04 bash sleep 5 amp amp
  • k8s-集群搭建的三种方式和区别,kubeadm、minikube,二进制包

    k8s 集群搭建的三种方式 xff0c 目前主流的搭建k8s集群的方式有kubeadm minikube xff0c 二进制包 kubeadm 是一个工具 xff0c 用于快速搭建kubernetes集群 xff0c 目前应该是比较方便和推
  • 精确算法、启发式算法、元启发式算法及增长方式浅析

    组合优化问题是通过用数学方法的研究去寻找离散事件的最优编排 分组 次序或筛选等 xff0c 其变量是离散分布的 对于结构化的组合优化问题 xff0c 其解空间的规模能够得到控制 xff0c 对于这样的问题 xff0c 使用精确算法就可以求得
  • 重构一个快不可维护的项目

    历史原因 xff0c 接手了一个一直堆业务逻辑 xff0c 没有重构过的项目 xff0c 简单看了一下代码就感觉麻头皮 xff0c 满目都是一个方法里面大段的代码 xff0c 阅读起来极度困难 可以合并的类没有合并 xff0c 导致一个请求
  • 芯片端子的多路复用

    嵌入式软件的开发 xff0c 经常要和芯片打交道 xff0c 和个人电脑的通用平台的CPU使用X86或X64架构不同 xff0c 嵌入式电子产品使用的主控芯片是各种各样的 xff0c 从8051单片机 xff0c 到ARM Cortex M
  • 树莓派学习笔记——获取树莓派CPU温度

    0 前言 本文通过文件操作读取树莓派CPU温度 xff0c 在linux系统中任何设备的操作都被抽象成为文件读写 xff0c 通过读取 sys class thermal thermal zone0 temp文件中的内容便获得树莓派CPU的
  • DHT11温湿度传感器

    1 封装信息 2 DHT11通讯总介 微处理器与DHT 11之间的通讯和同步 xff0c 采用单总线数据格式 xff0c 一次通讯时间4ms左右 xff0c 数据分小数部分和整数部分 一次完整的数据传输为40bit xff0c 高位先出 数
  • does not support raise

    This plugin does not support propagateSizeHints This plugin does not support raise arm平台界面无法显示 xff0c 有如上日志 该系统上安装的是5 11
  • docker jvm 内存限制

    docker 容器提供了相关的内存限制 具体使用方式如 xff1a m 512m 完整例子 docker run rm m 512m e JAVA OPTS 61 Xmx512m tomcat 8 通过 m 进行限制 但是在实际应用重 xf
  • DES加密算法—实现(C语言)

    http www iteye com topic 478024 DES xff08 Data Encrypt Standard数据库加密标准 xff09 是迄今为止使用最广泛的加密体制 初学信息安全的新生 xff0c 一般都会被老师要求实现