分组加密算法在加解密中十分常见,因其安全性高,计算速度快。常用的有DES、AES、IDEA和RC6等 。

由于DES的安全性存在争议,且56位的密钥太短(1997年RSA悬赏破解),现在使用的是3DES和AES(高级加密标准)。

下面说一说DES,数据加密标准(DES)是一个分组加密算法,也是对称加密算法,加解密的密钥一样。

DES采用Feistel结构设计,处理的明文分组为64位,有效密钥为56位,输出密文为64位,是具有16轮迭代的分组对称密码算法。

DES算法

 

   
   
   
   
  1. /* 
  2. DES算法,明文分组为64位(不足64位时补0),有效密钥56位,输出密文64位,16轮迭代 
  3. 由于没有保存长度信息,对于可能有填充部分,最后解密的明文最后一块可能会出现多余字符 
  4. 本程序的位从右往左为0~63() 
  5. */ 
  6.  
  7. #include 
  8. #include 
  9. #include 
  10.  
  11. unsigned char IP[64+1] = { 
  12. 58,50,42,34,26,18,10,2, 
  13. 60,52,44,36,28,20,12,4, 
  14. 62,54,46,38,30,22,14,6, 
  15. 64,56,48,40,32,24,16,8, 
  16. 57,49,41,33,25,17,9,1, 
  17. 59,51,43,35,27,19,11,3, 
  18. 61,53,45,37,29,21,13,5, 
  19. 63,55,47,39,31,23,15,7,0}; 
  20.  
  21. unsigned char IPRev[64+1] = { 
  22. 40,8,48,16,56,24,64,32, 
  23. 39,7,47,15,55,23,63,31, 
  24. 38,6,46,14,54,22,62,30, 
  25. 37,5,45,13,53,21,61,29, 
  26. 36,4,44,12,52,20,60,28, 
  27. 35,3,43,11,51,19,59,27, 
  28. 34,2,42,10,50,18,58,26, 
  29. 33,1,41,9,49,17,57,25,0}; 
  30.  
  31. unsigned char EExt[48+1] = { 
  32. 32,1,2,3,4,5, 
  33. 4,5,6,7,8,9, 
  34. 8,9,10,11,12,13, 
  35. 12,13,14,15,16,17, 
  36. 16,17,18,19,20,21, 
  37. 20,21,22,23,24,25, 
  38. 24,25,26,27,28,29, 
  39. 28,29,30,31,32,1,0}; 
  40.  
  41. unsigned char S[8][64] ={ 
  42. {14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7, 
  43. 0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8, 
  44. 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0, 
  45. 15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13},{ 
  46. 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10, 
  47. 3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5, 
  48. 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15, 
  49. 13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9},{ 
  50. 10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8, 
  51. 13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1, 
  52. 13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7, 
  53. 1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12},{ 
  54. 7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15, 
  55. 13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9, 
  56. 10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4, 
  57. 3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14},{ 
  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. 12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11, 
  63. 10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8, 
  64. 9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6, 
  65. 4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13},{ 
  66. 4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1, 
  67. 13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6, 
  68. 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2, 
  69. 6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12},{ 
  70. 13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7, 
  71. 1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2, 
  72. 7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8, 
  73. 2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11}}; 
  74.  
  75. unsigned char P[56+1] = { 
  76. 16,7,20,21,29,12,28,17, 
  77. 1,15,23,26,5,18,31,10, 
  78. 2,8,24,14,32,27,3,9, 
  79. 19,13,30,6,22,11,4,25,0}; 
  80.  
  81. unsigned char PC1[56+1] = { 
  82. 57,49,41,33,25,17,9, 
  83. 1,58,50,42,34,26,18, 
  84. 10,2,59,51,43,35,27, 
  85. 19,11,3,60,52,44,36, 
  86. 63,55,47,39,31,23,15, 
  87. 7,62,54,46,38,30,22, 
  88. 14,6,61,53,45,37,29, 
  89. 21,13,5,28,20,12,4,0}; 
  90.  
  91. unsigned char PC2[48+1] = { 
  92. 57,49,41,33,25,17,9,1, 
  93. 58,50,42,34,26,18,10,2, 
  94. 59,51,43,35,27,19,11,3, 
  95. 60,52,44,36,63,55,47,39, 
  96. 31,23,15,7,62,54,46,38, 
  97. 30,22,14,6,61,53,45,37,0}; 
  98.  
  99. unsigned char LS[16] = { 
  100. 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}; 
  101.  
  102. FILE *fp; 
  103.  
  104. unsigned long long Message; 
  105. int flag; 
  106. unsigned long long keys[16]; 
  107.  
  108. void getMessage(char mode); 
  109. unsigned long long Rep(unsigned char rp[],unsigned long long s);//置换 
  110. unsigned int SBoxC(unsigned long long x); 
  111. void GenKeys(char mode); 
  112.  
  113. unsigned int L,R; 
  114. unsigned long long K; 
  115.  
  116. int main(int argc, char *argv[]) 
  117.     char mode; 
  118.     char filename[256]; 
  119.     unsigned char key[10]; 
  120.     mode = *argv[1]; 
  121.     strcpy(filename,argv[2]); 
  122.      
  123.     if(argc != 4) 
  124.     { 
  125.         printf("参数有错误!\n"); 
  126.         exit(0); 
  127.     }  
  128.     if(strlen(argv[3])!=8) 
  129.     { 
  130.         printf("密钥长度不正确!"); 
  131.         exit(0); 
  132.     } 
  133.     strcpy(key,argv[3]); 
  134. /*  printf("请选择操作方式:加密 e ,解密 d :  "); 
  135.     scanf("%c",&mode); 
  136.     printf("请输入文件名:"); 
  137.     scanf("%s",filename); 
  138.     printf("请输入密钥(64bit):"); 
  139.     scanf("%s",key); */ 
  140.      
  141. //  printf("%s",filename); 
  142. //  system("pause"); 
  143.     if((fp=fopen(filename,"rb")) == NULL) 
  144.     { 
  145.         printf("文件无法打开"); 
  146.         exit(0); 
  147.     } 
  148.  
  149.     int inc = 0; 
  150.     K = 0; 
  151.     for(inc = 0 ;inc < 8; inc++) 
  152.         K |= (((unsigned long long)key[inc])<<((7-inc)<<3)); 
  153. #ifdef DEBUG 
  154.     printf(" K %016llx ",K); 
  155. #endif 
  156.     FILE *fpOut; 
  157.     char fileOut[200]; 
  158.     if(mode == 'e'
  159.         strcat(strcpy(fileOut,"ED\0"),filename); 
  160.     else 
  161.         strcat(strcpy(fileOut,"DD\0"),filename+2); 
  162.     fpOut= fopen(fileOut,"wb"); 
  163. //  fseek(fp, 0, SEEK_END); 
  164. //  fgetpos(fp, &pos); 
  165.     flag = 1;//判断是否结束 
  166.     int T; 
  167.      
  168.     GenKeys(mode); 
  169.      
  170.     getMessage(mode); 
  171.     while(flag) 
  172.     { 
  173.         Message = Rep(IP,Message); 
  174.         L = Message>>32; 
  175.         R = Message; 
  176.  
  177.         int i =0; 
  178.         for(i =0 ; i < 16; i++) 
  179.         { 
  180.             T = R;       
  181.             R = Rep(P,SBoxC(Rep(EExt,(unsigned long long)R)^keys[i]))^L; 
  182.             L = T; 
  183.         } 
  184.         Message = (((unsigned long long)R)<<32)|L; 
  185.         Message = Rep(IPRev,Message); 
  186.         if(mode == 'e'
  187.             fwrite(&Message,1,8,fpOut); 
  188.         else 
  189.         { 
  190.         Message = (Message>>56)|((Message&0x00ff000000000000)>>40)|((Message&0x0000ff0000000000)>>24)|((Message&0x000000ff00000000)>>8)| 
  191.                 (Message<<56)|((Message&0x000000000000ff00)<<40)|((Message&0x0000000000ff0000)<<24)|((Message&0x00000000ff000000)<<8); 
  192.             fwrite(&Message,1,8,fpOut); 
  193.         } 
  194.    
  195. /*      for(i = 0 ; i < 8 ; i++) 
  196.         { 
  197.             int out =(Message&(0x00000000000000ff<<(i*8))>>(i*8)); 
  198.             fwrite(&out,1,1,fpOut); 
  199.         }  */ 
  200.         getMessage(mode); 
  201.     } 
  202.      
  203.     fclose(fp); 
  204.     fclose(fpOut); 
  205.     return 0; 
  206.  
  207. void getMessage(char mode) 
  208.     Message = 0; 
  209.     flag = fread((void *)&Message,1,8,fp); 
  210. //  printf(" flag = %d %d %d ",flag,feof(fp),ferror(fp)); 
  211.     if(flag == 0) 
  212.     { 
  213.         return
  214.     } 
  215. #ifdef DEBUG 
  216.     printf("Mm %016llx ",Message); 
  217. #endif 
  218.     if(mode == 'e'
  219.     Message = (Message>>56)|((Message&0x00ff000000000000)>>40)|((Message&0x0000ff0000000000)>>24)|((Message&0x000000ff00000000)>>8)| 
  220.                 (Message<<56)|((Message&0x000000000000ff00)<<40)|((Message&0x0000000000ff0000)<<24)|((Message&0x00000000ff000000)<<8); 
  221. #ifdef DEBUG 
  222.     printf("Mess %016llx ",Message); 
  223. //  system("pause"); 
  224. #endif 
  225.  
  226. unsigned long long Rep(unsigned char rp[],unsigned long long s)//置换 
  227. #ifdef DEBUG 
  228. printf("in Rep  "); 
  229. #endif 
  230.     int i = 0; 
  231.     unsigned long long ans=0; 
  232.     unsigned long long con = 1; 
  233.     for(i = 0 ; i < strlen(rp); i++) 
  234.     { 
  235.         ans |= ((s&(con << (rp[i]-1)))>> (rp[i]-1))<
  236.         #ifdef DEBUG 
  237.         printf("time= %d ans %016llx ",i,ans); 
  238.         #endif 
  239. //      system("pause"); 
  240.     } 
  241. #ifdef DEBUG 
  242. printf(" Rep end "); 
  243. #endif 
  244.     return ans; 
  245.  
  246. unsigned int SBoxC(unsigned long long x) 
  247. #ifdef DEBUG 
  248. printf("in Sbox  "); 
  249. #endif 
  250.     int i = 0 , ans = 0; 
  251.     unsigned long long con = 0x3f; 
  252.     int t1_6 = 0,tr=0,tc=0; 
  253.     for(i = 0; i < 8; i++ ) 
  254.     { 
  255. #ifdef DEBUG 
  256. printf(" Sbox For Begin  "); 
  257. #endif 
  258.         t1_6 = (x & (con <<(i*6)))>>(i*6); 
  259.         tr = ((t1_6&(1<<5))>>4)|(t1_6&1); 
  260.         tc = (t1_6&0x1f)>>1; 
  261.         ans|=(S[7-i][(tr<<4)+tc])<<(i*4); 
  262.  
  263. #ifdef DEBUG 
  264.         printf(" ii = %d %x ",i,ans); 
  265.         system("pause"); 
  266.         printf(" Sbox For end  "); 
  267. #endif 
  268.     } 
  269. #ifdef DEBUG 
  270. printf(" Sbox end  "); 
  271. #endif 
  272.     return ans; 
  273.  
  274. unsigned int C,D; 
  275. void GenKeys(char mode) 
  276.     unsigned long long con = 0x0fffffff; 
  277.     K = Rep(PC1,K); 
  278.     C = (K&(con<<28))>>28; 
  279.     D = K&con; 
  280.     int i; 
  281.     if(mode == 'e'
  282.     { 
  283.         for(i = 0; i < 16; i++) 
  284.         { 
  285.             C = (C<>(32-LS[i])); 
  286.             D = (D<>(32-LS[i])); 
  287.             K = (C<<28)|D; 
  288.             keys[i] = Rep(PC2,K); 
  289.         } 
  290.     } 
  291.     else 
  292.     { 
  293.         for(i = 0; i < 16; i++) 
  294.         { 
  295.             C = (C<>(32-LS[i])); 
  296.             D = (D<>(32-LS[i])); 
  297.             K = (C<<28)|D; 
  298.             keys[15 - i] = Rep(PC2,K); 
  299.         } 
  300.     } 

编译器使用的是MingwGcc编译器。