DES加密算法(框图流程详细分析)(C++实现)

DES加解密算法C++

  • (一)题目
  • (二)分析、加解密算法流程图
    • 1.加密解密部分
    • 2.子密钥部分
    • 3.加密解密整体图
  • (三)整体代码
  • (四)运行结果

本文是课堂编程作业的总结,请于2020年5月20日以前禁止南京地区,东南大学大学的同学直接参考借鉴,以避免作业出现雷同,造成成绩判定纠纷。
(一)题目

在这里插入图片描述

(二)分析、加解密算法流程图

首先明确,DES的加解密流程框图是一样的,
区别在于:
加密是明文输入,密文输出,子密钥使用顺序是下标从0到15
解密是密文输入,明文输出,子密钥使用顺序是下标从15到0

1.加密解密部分

1.1加密解密轮函数(一轮)
在这里插入图片描述

1.2加密部分
在这里插入图片描述

1.3解密部分
在这里插入图片描述

2.子密钥部分

2.1子密钥轮函数(一轮)
在这里插入图片描述

16轮子密钥过程
在这里插入图片描述

3.加密解密整体图

3.1整体加密
在这里插入图片描述

3.2整体解密
在这里插入图片描述

(三)整体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
#include<iostream>
#include<iomanip>
using namespace std;


/******************************求密钥部分**************************************/

//置换选择1  
void Permutation_1(int Before[], int After[])
{
    int Permutation_1[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 };
    for (int i = 0; i < 56; i++)
    {
        After[i] = Before[Permutation_1[i] - 1];
    }
}

//56位数组   分割成    左右两个28位数组  
void Segmentation_56_28(int Input[], int C_Output[], int D_Output[])
{
    for (int i = 0; i < 28; i++)
    {
        C_Output[i] = Input[i];
        D_Output[i] = Input[i + 28];
    }
}

//循环左移函数
void Circulation_Left_Move(int Move_bits, int Input[28])
{
    int a = Input[0];
    int b = Input[1];

    for (int i = 0; i < 28 - Move_bits; i++)
    {
        Input[i] = Input[i + Move_bits];
    }

    if (Move_bits == 1)
    {
        Input[27] = a;
    }

    if (Move_bits == 2)
    {
        Input[26] = a;
        Input[27] = b;
    }

}

//两个28位数组组成  56位数组
void Combine_C_And_D(int Left_Output[28], int Right_Output[28], int Output[56])
{
    for (int i = 0; i < 28; i++)
    {
        Output[i] = Left_Output[i];
        Output[i + 28] = Right_Output[i];
    }
}

//置换选择2
void Permutation_2(int Left_And_right[56], int K_count, int K[][48])
{
    int Permutation_2[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 };
    for (int i = 0; i < 48; i++)
    {
        K[K_count][i] = Left_And_right[Permutation_2[i]-1];
    }
}

//轮函数求密钥K[16][48]    (一轮)    
void Wheel_Structure_Key(int K_count, int Move_bits[], int K[16][48], int C_Input[28], int D_Input[28])
{
    //C_Input[28], int D_Input[28]按照   由轮数确定的循环移动个数来进行移位
    Circulation_Left_Move(Move_bits[K_count], C_Input);
    Circulation_Left_Move(Move_bits[K_count], D_Input);
    cout << "第" << K_count <<setw(2)<<"轮子密钥:";

    /*cout << "左半边C[28]=";
    for (int i = 0; i < 28; i++)
    {
        cout << C_Input[i];
    }
    cout << endl;

    cout << "右半边D[28]=";
    for (int i = 0; i < 28; i++)
    {
        cout << D_Input[i];
    }
    cout << endl;*/

    //两个28位数组组成  56位数组
    int C_And_D_Output[56];
    Combine_C_And_D(C_Input, D_Input, C_And_D_Output);
   
    /*cout << "C_And_D_Output[]=";
    for (int i = 0; i < 56; i++)
    {
        cout << C_And_D_Output[i];
    }
    cout << endl;*/
   
    //置换选择2   生成密钥K[k_count][]
    Permutation_2(C_And_D_Output, K_count, K);
    cout << "K["<<K_count<<"][48]=";
    for (int i = 0; i < 48; i++)
    {
        cout << K[K_count][i];
    }
    cout << endl;

}

//制作所有16轮密钥K[16][48]  
void Make_All_Key(int Key[], int K[16][48])
{
    //制作有效的56位密钥//OK
    int Useful_Key[56];
    Permutation_1(Key, Useful_Key);
   
    ///
    /*  cout << "64位密钥Key[64]去除8位校验码后的56位Useful_Key[56]=";
    for (int i = 0; i < 56; i++)
    {
        cout << Useful_Key[i];
    }
    cout << endl; */



    //将56位有效密钥对半分为两密钥
    int C[28] ;
    int D[28];
    Segmentation_56_28(Useful_Key, C, D);
    //
    /*cout << "Useful_Key[56]的左半边C[28]=";
    for (int i = 0; i < 28; i++)
    {
        cout << C[i];
    }
    cout << endl;
    cout << "Useful_Key[56]的右半边D[28]=";
    for (int i = 0; i < 28; i++)
    {
        cout << D[i];
    }
    cout << endl;*/
   
    //左循环移位位数数组
    int Move_bits[16] = { 1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1 };
    for (int K_count = 0; K_count < 16; K_count++)
    {
        Wheel_Structure_Key(K_count, Move_bits, K, C, D);      
    }

}


/******************************DES   明文加密,密文解密    部分**************************************/

//初始置换IP  
void Initial_Permutation_IP(int Before[64],int After[64])
{
    int IP[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};
    for (int i = 0; i < 64; i++)
    {
        After[i] = Before[IP[i]-1];
    }
}

//64位数组   分割成    左右两个32位数组  
void Segmentation_64_32(int Input[64],int Left_Output[32],int Right_Output[32])
{
    for (int i = 0; i < 32; i++)
    {
        Left_Output[i] = Input[i];
        Right_Output[i] = Input[i+32];
    }

}

//扩展置换运算E
void Extended_Arithmetic_Permutation_E(int BeforeE[32],int AfterE[48])
{
    int Extended_Arithmetic_Permutation_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};
    for (int i = 0; i < 48; i++)
    {
        AfterE[i] = BeforeE[Extended_Arithmetic_Permutation_E[i]-1];
    }
}

//置换P
void Permutation_P(int BeforeP[32], int AfterP[32])
{
    int Permutation_P[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 };
    for (int i = 0; i < 32; i++)
    {
        AfterP[i] = BeforeP[Permutation_P[i]-1];
    }
}

//32位的异或运算(模2加法)
void XOR_32(int Input_1[32],int Input_2[32],int Output[32])
{
    for (int i = 0; i < 32; i++)
    {
        Output[i] = (Input_1[i]+ Input_2[i]) % 2;
    }
}

//48位的异或运算(模2加法)
void XOR_48(int Input[48], int K_count, int K[16][48], int Output[48])
{
    for (int i = 0; i < 48; i++)
    {
        Output[i] = (Input[i] + K[K_count][i]) % 2;
    }
}

//代换选择S盒
void S(int Input[48], int Output[32])
{
    int S[8][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}},
        {{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 (int i = 0; i< 8; i++)
    {
        int j = Input[i * 6] * 2 + Input[i * 6 + 5];
        int k = Input[i * 6+1] * 8 + Input[i * 6+2] * 4 + Input[i * 6+3] * 2 + Input[i * 6+4] * 1;
        int s = S[i][j][k];

        //int s转二进制
        int  remainder;//余数
       
        for (int index = 0; index < 4; index++)
        {
            remainder = s % 2;  //s除以2的余数
            s = s / 2;  //s被2整除的商
            Output[i * 4 + 3 - index] = remainder;  
        }
       /*int  index = 0;//计数量
        while (s != 0)//为啥这样写的while()不行
        {
            remainder = s % 2;  //s除以2的余数
            s = s / 2;  //s被2整除的商
            Output[i*4+3-index] = remainder;  
            index++;
        }*/
       

     }
}

//轮函数(密钥为K[K_count][48]的  一轮   轮函数)
void Wheel_Structure(int K_count,int K[16][48],   int Left_Input[32],int Right_Input[32] )
{
   
    //先把Right_Input[32]数组赋值给 中间变量数组Flag[32] 待到合适的时机再赋值给Left_Input[32]
    int Flag[32] = {0};
    for (int i = 0; i < 32; i++)
    {
        Flag[i] = Right_Input[i];
    }
    //cout << endl;
    //cout << "第" << K_count <<"轮解密"<< endl;
    //
    /*cout << "Flag[]=";
    for (int i = 0; i < 32; i++)
    {
        cout << Flag[i];
    }
    cout << endl;*/
   

    //扩展置换运算E
    int Output_E[48];//扩展置换运算E的输出
    Extended_Arithmetic_Permutation_E(Right_Input,  Output_E);
    /*cout << "E[]=";
    for (int i = 0; i < 48; i++)
    {
        cout << Output_E[i];
    }
    cout << endl;*/
   

    //扩展置换运算E
    int Output_XOR_48[48];//扩展置换运算E的输出
    XOR_48(Output_E, K_count, K, Output_XOR_48);////////////////////////////////////////////////////////////////
    /*cout << "XOR_48[]=";
    for (int i = 0; i < 48; i++)
    {
        cout << Output_XOR_48[i];
    }
    cout << endl;*/
   
    //代换选择S盒
    int Output_S[32];//代换选择S盒的输出
    S(Output_XOR_48,  Output_S);
    /*cout << "S[]=";
    for (int i = 0; i < 32; i++)
    {
        cout << Output_S[i];
    }
    cout << endl;*/
   

    //置换P
    int Output_P[32];//置换P的输出
    Permutation_P( Output_S, Output_P);
    /*cout << "P[]=";
    for (int i = 0; i < 32; i++)
    {
        cout << Output_P[i];
    }
    cout << endl;*/
   

    //32位的异或运算
    XOR_32(Left_Input, Output_P, Right_Input);
    /*cout << "NextRight[]=";
    for (int i = 0; i < 32; i++)
    {
        cout << Right_Input[i];
    }
    cout << endl;*/
   

    //将Flag[32]赋值给Left_Input[32]
    for (int i = 0; i < 32; i++)
    {
        Left_Input[i] = Flag[i];
    }
    /*  cout << "Next_Left[]=";
    for (int i = 0; i < 32; i++)
    {
        cout << Flag[i];
    }
    cout << endl;*/


}

//左右交换     两个32位数组组成  64位数组
void Left_Right_Change_And_Combine(int Left_Output[32], int Right_Output[32],int Output[64])
{
    for (int i = 0; i < 32; i++)
    {
     Output[i] = Right_Output[i] ;
     Output[i + 32]=Left_Output[i] ;
    }
}

//逆初始置换Inverse_IP  
void Inverse_Initial_Permutation_IP(int Before[64], int After[64])
{
    int Inverse_IP[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     };
    for (int i = 0; i < 64; i++)
    {
        After[i] = Before[Inverse_IP[i] - 1];
    }
}

//加密
void E_M_to_C(int M[64],int K[16][48],int C[64])
{
    //初始置换IP
    int After_IP[64] = { 0 };
    Initial_Permutation_IP(M, After_IP);
   
    //64位数组   分割成    左右两个32位数组
    int Left[32];
    int Right[32];
    Segmentation_64_32(After_IP,Left ,Right );

    //对左右两数组  进行16轮 轮函数加密
    for (int K_count = 0; K_count < 16; K_count++)   //K_count从0到15是加密
    {
        Wheel_Structure(K_count, K, Left, Right);
    }

    //左右交换    两32位数组  组成  64位数组
    int Output_Segmentation[64];
    Left_Right_Change_And_Combine(Left, Right, Output_Segmentation);

    //逆初始置换Inverse_IP
    Inverse_Initial_Permutation_IP(Output_Segmentation, C);
}

//解密
void D_C_to_M(int C[64], int K[16][48], int M[64])
{
    //初始置换IP     OK
    int After_IP[64] = { 0 };
    Initial_Permutation_IP(C, After_IP);
    /*cout << "初始置换后的数组[64]=";
    for (int i = 0; i < 64; i++)
    {
        cout << After_IP[i];
    }
    cout << endl;*/
   

    //64位数组   分割成    左右两个32位数组  OK
    int Left[32];
    int Right[32];
    Segmentation_64_32(After_IP, Left, Right);
    /*  cout << "Left[]=";
    for (int i = 0; i < 32; i++)
    {
        cout << Left[i];
    }
    cout << endl;
    cout << "Right[]=";
    for (int i = 0; i < 32; i++)
    {
        cout << Right[i];
    }
    cout << endl;*/

    //对左右两数组  进行16轮 轮函数加密
    for (int K_count = 15; K_count >= 0; K_count--)   //K_count从15到0是解密
    {
        Wheel_Structure(K_count, K, Left, Right);
    }

    //左右交换    两32位数组  组成  64位数组
    int Output_Segmentation[64];
    Left_Right_Change_And_Combine(Left, Right, Output_Segmentation);

    //逆初始置换Inverse_IP
    Inverse_Initial_Permutation_IP(Output_Segmentation, M);
}


/******************************数制转换部分**************************************/

//将十六进制转为二进制
void Convertion_16_2(unsigned long long k, int Positive_Binary[])
{
    unsigned  remainder;//余数
    unsigned   index = 64;//计数量
    while (k != 0)
    {
        remainder = k % 2;  //m除以2的余数
        k = k / 2;  //m被2整除的商
        Positive_Binary[index-1] = remainder;  //将余数存放在数组Positive_Binary[BinarySize]中,这里先正序排放,下一步要倒叙排列
        index--;
    }

}
//将二进制转为十进制
void Convertion_2_16(int M[], unsigned long long& m)
{
    unsigned long long Sum=0;
    for (int i=0;i<64;i++)
    {
        unsigned long long Pow = 1;
        for (int j = 0; j < 63 - i; j++)//这里注意j=0,j<63-i
        {
            Pow = Pow * 2;
        }
        //cout << "Pow=" << Pow<<endl;
        Sum = Sum + Pow * M[i];
    }
    m = Sum;
}

int main()
{
    unsigned long long k = 0x133457799BBCDFF1;//密钥k(0x十六进制)
    unsigned long long c = 0x85E813540F0AB405;//密文c (0x十六进制)
    unsigned long long m=0;//明文m
    int Key[64] = {0}; //密钥数组(二进制)       初值全为0
    int Cipher[64] = {0};    //密文数组(二进制)       初值全为0
    int M[64] = {0};   //明文数组(二进制)       初值全为0
    int K[16][48]={0};//16组子密钥(二进制)   初值全为0

    //十六进制密钥转为二进制,并输出二进制密钥
    Convertion_16_2( k, Key);
    cout << "密钥[64]=";
    for (int i = 0; i < 64; i++)
    {
        cout << Key[i];
    }
    cout << endl;
   
    //十六进制密文转为二进制,并输出二进制密文
    Convertion_16_2(c, Cipher);
    cout << "密文[64]=";
    for (int i = 0; i < 64; i++)
    {
        cout << Cipher[i];
    }
    cout << endl<<endl;
   
    //制作16轮所有的密钥
    Make_All_Key( Key,  K);
    cout << endl;
    //解密,并输出明文
    D_C_to_M(Cipher, K, M);
    Convertion_2_16(M, m);
    cout << "明文[64]=";
    for (int i = 0; i < 64; i++)
    {
        cout << M[i];
    }
    cout << endl;
    cout <<"明文为:"<< hex << m;
}

(四)运行结果

解密结果为:“123456789ABCDEF”(十六进制表示)
在这里插入图片描述