数据加密标准DES加密算法是一种对称加密算法,DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。
下面是我自己用C语言实现的DES加密代码,如有错误,欢迎指正!
1 #include2 #include 3 #include<string.h> 4 5 //IP初始置换表 6 int IP_Table[64]={ 7 58,50,42,34,26,18,10, 2,60,52,44,36,28,20,12, 4, 8 62,54,46,38,30,22,14, 6,64,56,48,40,32,24,16, 8, 9 57,49,41,33,25,17, 9, 1,59,51,43,35,27,19,11, 3, 10 61,53,45,37,29,21,13, 5,63,55,47,39,31,23,15, 7 11 }; 12 13 //IP逆置换表 14 int IPR_Table[64] = { 15 40,8,48,16,56,24,64,32,39,7,47,15,55,23,63,31, 16 38,6,46,14,54,22,62,30,37,5,45,13,53,21,61,29, 17 36,4,44,12,52,20,60,28,35,3,43,11,51,19,59,27, 18 34,2,42,10,50,18,58,26,33,1,41,9,49,17,57,25 19 }; 20 21 //E位选择表(扩展置换表) 22 int E_Table[48] = { 23 32,1,2,3,4,5,4,5,6,7,8,9, 24 8,9,10,11,12,13,12,13,14,15,16,17, 25 16,17,18,19,20,21,20,21,22,23,24,25, 26 24,25,26,27,28,29,28,29,30,31,32,1 27 }; 28 int P_Table[32] = { 29 16,7,20,21,29,12,28,17,1,15,23,26,5,18,31,10, 30 2,8,24,14,32,27,3,9,19,13,30,6,22,11,4,25 31 }; 32 33 int PC1_Table[56] = { 34 57,49,41,33,25,17,9,1,58,50,42,34,26,18, 35 10,2,59,51,43,35,27,19,11,3,60,52,44,36, 36 63,55,47,39,31,23,15,7,62,54,46,38,30,22, 37 14,6,61,53,45,37,29,21,13,5,28,20,12,4 38 }; 39 //PC2选位表(密钥生成置换表2) 40 int PC2_Table[48] = { 41 14,17,11,24,1,5,3,28,15,6,21,10, 42 23,19,12,4,26,8,16,7,27,20,13,2, 43 41,52,31,37,47,55,30,40,51,45,33,48, 44 44,49,39,56,34,53,46,42,50,36,29,32 45 }; 46 //左移位数表 47 int LOOP_Table[16] = { 48 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 49 }; 50 // S盒 51 int S_Box[8][4][16] = { 52 // S1 53 14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7, 54 0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8, 55 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0, 56 15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13, 57 //S2 58 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10, 59 3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5, 60 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15, 61 13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9, 62 //S3 63 10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8, 64 13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1, 65 13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7, 66 1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12, 67 //S4 68 7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15, 69 13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9, 70 10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4, 71 3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14, 72 //S5 73 2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9, 74 14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6, 75 4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14, 76 11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3, 77 //S6 78 12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11, 79 10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8, 80 9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6, 81 4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13, 82 //S7 83 4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1, 84 13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6, 85 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2, 86 6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12, 87 //S8 88 13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7, 89 1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2, 90 7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8, 91 2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11 92 }; 93 void ShowArray(int *array,int num); 94 void BitsCopy(int *DatOut,int *DatIn,int Len); 95 //将字符数组转换成二进制数组 96 void CharToBit(char *input,int *output,int bits) 97 { 98 int i=0; 99 for(i=0;i ) 100 { 101 output[i]=(input[i/8]>>(i%8))&1; 102 } 103 } 104 105 //将二进制数组转换成字符数组 106 void BitToChar(int *input, char *output, int bits) 107 { 108 int i=0; 109 for(i=0;i<(bits/8);i++) 110 { 111 output[i]=0; 112 } 113 for(i=0;i ) 114 { 115 output[i/8]|=input[i]<<(i%8); 116 } 117 } 118 //完成异或操作 119 void Xor(int InA[],int InB[],int len) 120 { 121 int i=0; 122 for(i=0;i ) 123 { 124 InA[i]=InA[i]^InB[i]; //按位异或 125 } 126 } 127 128 //IP初始置换和逆置换函数,由table决定是逆置换还是初始置换 129 void IP_IPR(int input[64],int output[64],int table[64]) 130 { 131 int i=0; 132 for(i=0;i<64;i++) 133 { 134 output[i]=input[table[i]-1]; 135 } 136 } 137 //E盒扩展 138 void E(int input[32],int output[48],int table[48]) 139 { 140 int i=0; 141 for(i=0;i<48;i++) 142 { 143 output[i]=input[table[i]-1]; 144 } 145 } 146 147 //P盒替代 148 void P(int input[32],int output[32],int table[32]) 149 { 150 151 int i=0; 152 for(i=0;i<32;i++) 153 { 154 output[i]=input[table[i]-1]; 155 } 156 } 157 158 //PC-1置换选择 159 void PC_1(int input[64],int output[56],int table[56]) 160 { 161 int i=0; 162 for(i=0;i<56;i++) 163 { 164 output[i]=input[table[i]-1]; 165 } 166 } 167 168 //PC-2置换选择 169 void PC_2(int input[56],int output[48],int table[48]) 170 { 171 int i=0; 172 for(i=0;i<48;i++) 173 { 174 output[i]=input[table[i]-1]; 175 } 176 } 177 178 //S盒压缩 179 void S(int input[48],int output[32],int table[8][4][16]) 180 { 181 int i,X,Y; // i为8个S盒 182 for(i=0,Y=0,X=0;i<8;i++,input+=6,output+=4) // 每执行一次,输入数据偏移6位 183 { // 每执行一次,输出数据偏移4位 184 Y=(input[0]<<1)+input[5]; // af代表第几行 185 X=(input[1]<<3)+(input[2]<<2)+(input[3]<<1)+input[4]; // bcde代表第几列 186 char temp=(char)table[i][4][16]; 187 CharToBit(&temp,output,4); // 把找到的点数据换为二进制 188 } 189 } 190 //F轮函数 191 void F_func(int input[32],int subkey[48]) 192 { 193 int MiR[48]={0}; 194 int temp[32]; 195 E(input,MiR,E_Table); // 输入32位通过E选位变为48位 196 printf("E盒扩展:\n"); 197 ShowArray(MiR,48); 198 Xor(MiR,subkey,48); // 和子密钥异或 199 S(MiR,input,S_Box); // S盒变换 200 printf("S盒替代:\n"); 201 ShowArray(input,32); 202 BitsCopy(temp,input,32); 203 P(temp,input,P_Table); // P置换后输出 204 printf("P盒置换:\n"); 205 ShowArray(input,32); 206 } 207 /*------------------------------- 208 把DatIn开始的长度位Len位的二进制 209 复制到DatOut后 210 --------------------------------*/ 211 void BitsCopy(int *DatOut,int *DatIn,int Len) // 数组复制 OK 212 { 213 int i=0; 214 for(i=0;i ) 215 { 216 DatOut[i]=DatIn[i]; 217 } 218 } 219 220 //子秘钥中循环左移函数 221 void RotateL(int input[28],int output[28], int loop) 222 { 223 BitsCopy(output,input+loop,28-loop); 224 BitsCopy(output+28-loop,input,loop); 225 } 226 227 //子秘钥生成 228 void subKey_fun(int input[64],int Subkey[16][48]) 229 { 230 int i=0; 231 int temp[56]; 232 int *KeyL=&temp[0],*KeyR=&temp[28]; 233 printf("***子秘钥的生成:***\n"); 234 PC_1(input,temp,PC1_Table); 235 printf("PC-1置换:\n"); 236 ShowArray(temp,56); 237 238 for(i=0;i<16;i++) 239 { 240 printf("子秘钥第%d:\n",i+1); 241 RotateL(KeyL,KeyL,LOOP_Table[i]); // 前28位左移 242 printf("循环左移后左部:\n"); 243 ShowArray(KeyL,28); 244 RotateL(KeyR,KeyR,LOOP_Table[i]); // 后28位左移 245 printf("循环左移后右部:\n"); 246 ShowArray(KeyR,28); 247 PC_2(temp,Subkey[i],PC2_Table); 248 printf("PC-2选择置换:\n"); 249 ShowArray(Subkey[i],48); 250 251 } 252 } 253 254 255 /*---------------------------------- 256 二进制密文转换为十六进制 257 需要16个字符表示 258 -----------------------------------*/ 259 void BitToHex(char *DatOut,int *DatIn,int Num) 260 { 261 int i=0; 262 for(i=0;i 4;i++) 263 { 264 DatOut[i]=0; 265 } 266 for(i=0;i 4;i++) 267 { 268 DatOut[i] = DatIn[i*4]+(DatIn[i*4+1]<<1) 269 +(DatIn[i*4+2]<<2)+(DatIn[i*4+3]<<3); 270 if((DatOut[i]%16)>9) 271 { 272 DatOut[i]=DatOut[i]%16+'7'; // 余数大于9时处理 10-15 to A-F 273 } // 输出字符 274 else 275 { 276 DatOut[i]=DatOut[i]%16+'0'; // 输出字符 277 } 278 } 279 280 } 281 282 //DES加密 283 void DES_Dfun(int input[],char key_in[],char output[]) 284 { 285 int ML[32]={0},MR[32]={0}; 286 int temp1[64],temp2[32],temp3[64]; 287 int Subkey[16][48]; 288 int input_l[32]={0}; 289 int input_r[32]={0}; 290 int testi=0; 291 for(testi=0;testi<32;testi++) 292 { 293 input_l[testi]=input[testi]; 294 } 295 for(testi=0;testi<32;testi++) 296 { 297 input_r[testi]=input[32+testi]; 298 } 299 BitsCopy(ML,input_l,32); 300 BitsCopy(MR,input_r,32); 301 BitsCopy(temp1,input,64); 302 IP_IPR(temp1,input,IP_Table); //IP置换 303 printf("IP初始置换:\n"); 304 ShowArray(input,64); 305 CharToBit(key_in,temp3,64); 306 subKey_fun(temp3,Subkey); //子秘钥的生成 307 for(int i=0;i<16;i++) // 迭代16次 308 { 309 printf("***第%d轮迭代:***\n",i+1); 310 BitsCopy(temp2,MR,32); // 临时存储 311 F_func(MR,Subkey[i]); // F函数变换 312 Xor(MR,ML,32); // 得到Ri 313 BitsCopy(ML,temp2,32); // 得到Li 314 printf("ML:\n"); 315 ShowArray(ML,32); 316 printf("MR:\n"); 317 ShowArray(MR,32); 318 } 319 IP_IPR(input,temp1,IPR_Table); 320 BitToHex(output,input,64); 321 } 322 323 //输出字符数组 324 void ShowArray(int *array,int num) 325 { 326 int i; 327 for(i=0;i ) 328 { 329 printf("%d",array[i]); 330 } 331 printf("\n"); 332 } 333 334 int main() 335 { 336 int i=0; 337 char MyKey[9]={0}; // 初始密钥 8字节*8 338 char MyMessage[9]={0}; // 初始明文 339 int KeyBin[64]={0},MesBin[64]={0}; 340 char ciphertext[9]; 341 /*-----------------------------------------------*/ 342 343 printf("输入明文(8字节):\n"); 344 gets(MyMessage); // 明文 345 printf("输入密钥(8字节):\n"); 346 gets(MyKey); // 密钥 347 while(strlen(MyKey)!=8) // 不是8 提示错误 348 { 349 printf("请输入正确的密钥:\n"); 350 gets(MyKey); 351 i=0; 352 while(MyKey[i]!='\0') // 再次检测 353 { 354 i++; 355 } 356 } 357 CharToBit(MyMessage,MesBin,64); 358 DES_Dfun(MesBin,MyKey,ciphertext); 359 printf("明文已被加密!\n"); // 信息已加密 360 for(i=0;i<16;i++) 361 { 362 printf("%c ",ciphertext[i]); 363 } 364 printf("\n"); 365 system("pause"); 366 return 0; 367 /*------------------------------------------------*/ 368 }