密码学大作业记录(报告、指北)

得了70分,感觉还不错?

😃

实验要求

设计一个保密通信的协议,具体要求为:利用RSA公钥密码算法,为双方分配一个 AES算法的会话密钥,然后利用AES加密算法和分配的会话密钥,加解密传送的信息。

假设条件:假设通讯双方为A和B,并假设发方拥有自己的RSA公钥PKA和私钥SKA ,同时收方拥有自己的RSA公钥PKB和私钥SKB ,同时收发双方已经通过某种方式知道了双方的公钥。

大作业的要求:

  1. 作业需要先设计出保密通讯协议的过程和具体步骤;

  2. 分别编写A,B两个用户端的程序,写清楚两个程序分别要完成的功能,并能够在两个程序间进行通讯;

  3. 对AES加密的保密信息,要求采用CBC模式进行加密;

  4. 大作业的提交方式同实验报告的提交,也就是说既要提交程序实现的说明文档,也要提交源代码和可执行程序。

占总成绩的70%

预备工作

首先,你需要准备如下实验的代码,然后准备缝合:

  1. 计网的实验一,socket双人聊天

  2. AES代码

  3. RSA代码

ps: 如果你计网的实验一写的是多人聊天或者聊天室,恭喜你,写麻烦了,缝不进来

注意:也可以缝合计网实验3,实现加密文件传输,由于文件是二进制读取,而且是定长的,甚至会更加容易。

过程讲解

socket双人聊天

这一步就是计网lab1,关于原理、过程、代码细节不会的可以去看我的计网实验一的blog。已经会了的可以直接跳过。

AES代码

可以使用赵梓杰的代码,但是小问题在于这份代码只能加密数字,无法直接处理字符串,因此需要自己添加字符串转换和补全的内容。

不过由于要求是CBC模式,因此需要去git上自己找一个写下来。下面是我用的一个参考代码,来源是csdnC语言 实现AES_CBC_128_ZeroPadding 加解密算法下面给出便于缝合的代码

AES.h
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
#ifndef __AES_H_
#define __AES_H_


#include <string.h>
#include <stdio.h>
#include <stdlib.h>

//#define AESKEY "71412E2299B0EEA5"
#define AESIV "71412E2299B0EEA5"

typedef unsigned long DWORD;
typedef unsigned char UCHAR,*PUCHAR;
typedef void *PVOID,*LPVOID;
typedef unsigned char byte;
typedef DWORD *PDWORD,*LPDWORD;

#ifndef VOID
#define VOID void
#endif

#define Bits128 16
#define Bits192 24
#define Bits256 32


void AES_Init(int keySize, unsigned char* keyBytes);

void Cipher(unsigned char* input, unsigned char* output); // encipher 16-bit input
void InvCipher(unsigned char* input, unsigned char* output); // decipher 16-bit input


void SetNbNkNr(int keySize);
void AddRoundKey(int round); //轮密钥加
void SubBytes(void); //S盒字节代换
void InvSubBytes(void); //逆S盒字节代换
void ShiftRows(void); //行移位
void InvShiftRows(void);
void MixColumns(void); //列混淆
void InvMixColumns(void);
unsigned char gfmultby01(unsigned char b);
unsigned char gfmultby02(unsigned char b);
unsigned char gfmultby03(unsigned char b);
unsigned char gfmultby09(unsigned char b);
unsigned char gfmultby0b(unsigned char b);
unsigned char gfmultby0d(unsigned char b);
unsigned char gfmultby0e(unsigned char b);
void KeyExpansion(void); //密钥扩展
unsigned char* SubWord(unsigned char* word); //密钥S盒字代换
unsigned char* RotWord(unsigned char* word); //密钥移位


DWORD OnAesEncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer); //AES 加密数据
DWORD OnAesUncrypt(LPVOID InBuffer,DWORD InLength,LPVOID OutBuffer); //AES 解密数据


#endif
AES.cpp
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
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
#include "AES.h"

int Nb; // block size in 32-bit words. Always 4 for AES. (128 bits).
int Nk; // key size in 32-bit words. 4, 6, 8. (128, 192, 256 bits).
int Nr; // number of rounds. 10, 12, 14.

unsigned char key[32];
unsigned char w[16 * 15];
unsigned char State[4][4]; // 状态矩阵

// S盒
static unsigned char AesSbox[16 * 16]=
{
// populate the Sbox matrix
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/*0*/ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
/*1*/ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
/*2*/ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
/*3*/ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
/*4*/ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
/*5*/ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
/*6*/ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
/*7*/ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
/*8*/ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
/*9*/ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
/*a*/ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
/*b*/ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
/*c*/ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
/*d*/ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
/*e*/ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
/*f*/ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};

// 逆S盒
static unsigned char AesiSbox[16 * 16]=
{
// populate the iSbox matrix
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
/*0*/ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
/*1*/ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
/*2*/ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
/*3*/ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
/*4*/ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
/*5*/ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
/*6*/ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
/*7*/ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
/*8*/ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
/*9*/ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
/*a*/ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
/*b*/ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
/*c*/ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
/*d*/ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
/*e*/ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
/*f*/ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};

// 轮常量
static unsigned char AesRcon[11 * 4]=
{
0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00,
0x08, 0x00, 0x00, 0x00,
0x10, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00,
0x1b, 0x00, 0x00, 0x00,
0x36, 0x00, 0x00, 0x00
};


/**
*** 设置密钥长度Nk(单位 :Nb 个字节),轮数Nr,
***
*** 密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同
**/
void SetNbNkNr(int keySize)
{
Nb = 4;
if(keySize == Bits128)
{
Nk = 4; //4*4字节,128位密钥,10轮加密
Nr = 10;
}
else if(keySize == Bits192)
{
Nk = 6; //6*4字节,192位密钥,12轮加密
Nr = 12;
}
else if(keySize==Bits256)
{
Nk = 8; //8*4字节,256位密钥,14轮加密
Nr = 14;
}
}

/**
*** 密钥扩展函数(作用:得到10轮子密钥)
***
***Nk 密钥长度 = 4 (单位:4字节)
***Nr 加密轮数 = 10
***
***初始的128位密钥 key[4 * 4字节] = k[0] k[1] k[2] k[3]
*** k[4] k[5] k[6] k[7]
*** k[8] k[9] k[10] k[11]
*** k[12] k[13] k[14] k[15]
***
*** 扩展密钥W的初始值:
*** W0 = k[0] k[1] k[2] k[3]
*** W1 = k[4] k[5] k[6] k[7]
*** W2 = k[8] k[9] k[10] k[11]
*** W3 = k[12] k[13] k[14] k[15]
***
*** 注:Wi = w[4i] w[4i + 1] w[4i + 2] w[4i + 3]
***
*** 第0轮子密钥 :W0 W1 W2 W3
*** 第1轮子密钥 :W4 W5 W6 W7
*** 第2轮子密钥 :W8 W9 W10 W11
*** 第3轮子密钥 :W12 W13 W14 W15
*** 第4轮子密钥 :W16 W17 W18 W19
*** 第5轮子密钥 :W20 W21 W22 W23
*** 第6轮子密钥 :W24 W25 W26 W27
*** 第7轮子密钥 :W28 W29 W30 W31
*** 第8轮子密钥 :W32 W33 W34 W35
*** 第9轮子密钥 :W36 W37 W38 W39
*** 第10轮子密钥:W40 W41 W42 W43
***
**/
void KeyExpansion(void)
{
int row;
byte temp[4];
byte *ret;
memset(w, 0, 16 * 15);

// 扩展密钥初始值 W0 ~ W3
for(row = 0; row < Nk; row++) // 复制 key[0] ~ key[15] 到 W[0] ~ W[15]
{
w[4 * row + 0] = key[4 * row];
w[4 * row + 1] = key[4 * row + 1];
w[4 * row + 2] = key[4 * row + 2];
w[4 * row + 3] = key[4 * row + 3];
}

// 循环 40 轮 当前计算轮数 i = row - 4
// 第1轮: 输入 W0 W3 输出 W4
// 第2轮: 输入 W1 W4 输出 W5
// 第3轮: 输入 W2 W5 输出 W6
// 第4轮: 输入 W3 W6 输出 W7
// 第i轮: 输入 W(i - 1) W(i + 2) 输出 W(i + 3)
// 第40轮:输入 W39 W42 输出 W43
for(row = Nk; row < 4 * (Nr + 1); row++)
{
temp[0] = w[4 * row - 4]; //当前列的前一列
temp[1] = w[4 * row - 3];
temp[2] = w[4 * row - 2];
temp[3] = w[4 * row - 1];

// 新列以如下的递归方式产生:

// 逢nk时,对当前列的前一列作特殊处理
// 如果 row 是4的倍数,Wi = W(i-4) ⊕ T(W(i-1)) 注:函数T由3部分组成:字循环、字节代换和轮常量异或
// 如果 row 不是4的倍数,Wi = W(i-4) ⊕ W(i-1)

// 当 row 是4的倍数,计算 T(W(i-1))
if(row % Nk == 0)
{
// 先 “字循环” RotWord 再 “字节代换” SubWord
ret = SubWord(RotWord(temp));
temp[0] = ret[0];
temp[1] = ret[1];
temp[2] = ret[2];
temp[3] = ret[3];

// “轮常量异或” (将前两步的结果 和 轮常量AesRcon[j]进行异或,其中j表示轮数)
temp[0] = (byte)((int)temp[0] ^ (int) AesRcon[4 * (row / Nk) + 0]);
temp[1] = (byte)((int)temp[1] ^ (int) AesRcon[4 * (row / Nk) + 1]);
temp[2] = (byte)((int)temp[2] ^ (int) AesRcon[4 * (row / Nk) + 2]);
temp[3] = (byte)((int)temp[3] ^ (int) AesRcon[4 * (row / Nk) + 3]);
}
// 非 128位轮密钥K的情况
else if(Nk > 6 && (row % Nk == 4) )
{
ret = SubWord(temp);
temp[0] = ret[0];
temp[1] = ret[1];
temp[2] = ret[2];
temp[3] = ret[3];
}

w[4 * row + 0] = (byte) ((int) w[4 * (row - Nk) + 0] ^ (int)temp[0]);
w[4 * row + 1] = (byte) ((int) w[4 * (row - Nk) + 1] ^ (int)temp[1]);
w[4 * row + 2] = (byte) ((int) w[4 * (row - Nk) + 2] ^ (int)temp[2]);
w[4 * row + 3] = (byte) ((int) w[4 * (row - Nk) + 3] ^ (int)temp[3]);
} // for loop
}


/******密钥移位函数(字循环 函数)*****/

// 将1个字中的4个字节循环左移1个字节。
// 即将输入字[b0, b1, b2, b3]变换成[b1,b2,b3,b0]。
unsigned char* RotWord(unsigned char word[])
{
static byte temp[4];
temp[0] = word[1];
temp[1] = word[2];
temp[2] = word[3];
temp[3] = word[0];
return temp;
}

/******密钥字代换函数*****/

//状态矩阵中的元素按照下面的方式映射为一个新的字节:
//把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。

unsigned char* SubWord(unsigned char word[])
{
int j;
static byte temp[4];

for(j = 0; j < 4; j++)
{
temp[j] = AesSbox[16 * (word[j] >> 4) + (word[j] & 0x0f)];
}
return temp;
}



/**
*** Aes加密函数 encrypt
***
*** 128位的输入明文分组State[4][4]
***
*** S0 S4 S8 S12 (单位:字节)
*** S1 S5 S9 S13
*** S2 S6 S10 S14
*** S3 S7 S11 S15
***
**/
void Cipher(unsigned char* input, unsigned char* output)
{
int i;
int round ;

// State[4][4] = 128位的输入明文分组
memset(&State[0][0], 0, 16);

for(i = 0; i < 4 * Nb; i++) // 这里是先写列后写行的,即输入是一列一列的进来的
{
State[i % 4][i / 4] = input[i]; // 换成先写行后写列也是可以的,只要在输出时也是这样就可以了
}

// 循环前进行一次轮密钥加
AddRoundKey(0); //轮密钥加

// 循环 第1轮 ~ 第9轮
for(round = 1; round <= (Nr - 1); round++) // main round loop
{
SubBytes(); //字节代换
ShiftRows(); //行移位
MixColumns(); //列混淆
AddRoundKey(round); //轮密钥加
}

// 第10轮没有列混淆
SubBytes(); //字节代换
ShiftRows(); //行移位
AddRoundKey(Nr); //轮密钥加

// 输出密文 16字节
for(i = 0; i < (4 * Nb); i++)
{
output[i] = State[i % 4][ i / 4];
}
}



/**
*** Aes解密函数 decrypt
***
*** 128位的输入密文分组State[4][4]
***
*** S0 S4 S8 S12 (单位:字节)
*** S1 S5 S9 S13
*** S2 S6 S10 S14
*** S3 S7 S11 S15
***
**/
void InvCipher(unsigned char* input, unsigned char* output)
{
int round;
int i;
memset(&State[0][0], 0, 16);

// State[4][4] = 128位的输入密文分组
for(i = 0; i < (4 * Nb); i++)
{
State[i % 4][ i / 4] = input[i];
}

// 循环前进行一次轮密钥加
AddRoundKey(Nr); //轮密钥加

// 循环 第9轮 ~ 第1轮
for(round = Nr - 1; round >= 1; round--)
{
InvShiftRows(); // 逆行移位
InvSubBytes(); // 逆字节代换
AddRoundKey(round); // 轮密钥加
InvMixColumns(); // 逆列混合变换
}

// 第0轮没有逆列混淆
InvShiftRows(); // 逆行移位
InvSubBytes(); // 逆字节代换
AddRoundKey(0); // 轮密钥加

// 输出明文 16字节
for(i = 0; i < (4 * Nb); i++)
{
output[i] = State[i % 4][ i / 4];
}
}

/****轮密钥加****/

// 根据传入的轮数来把状态矩阵State[i][j]与相应的W[4 * ((round * 4) + j) + i]异或
void AddRoundKey(int round)
{
int i, j; //i行 j列 // 因为密钥W(x)是一列一列排列的,W(x) = w[4x+0] w[4x+1] w[4x+2] w[4x+3]
// 即 w[4x+0] w[4x+1] w[4x+2] w[4x+3] x = (round * 4) + j
// k0 k4 k8 k12
for(j = 0; j < 4; j++) // k1 k5 k9 k13
{ // k2 k6 k10 k14
for(i = 0; i < 4; i++) // k3 k7 k11 k15
{
// 所以i行j列的下标是4 * ((round * 4) + j) + i即16 * round + 4 * j+ i
State[i][j]=(unsigned char)((int)State[i][j] ^ (int)w[4 * ((round * 4) + j) + i]);
}
}
}


/****字节代换函数****/

// 状态矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。
void SubBytes(void)
{
int i, j;
for(j = 0; j < 4; j++)
{
for(i = 0; i < 4; i++)
{
State[i][j] = AesSbox[State[i][j]];
//因为 16 * (State[i][j] >> 4) + State[i][j] & 0x0f = State[i][j]
}
}
}

/****逆字节代换函数****/

// 逆字节代换也就是查逆S盒来变换
void InvSubBytes(void)
{
int i, j;
for(j = 0; j < 4; j++)
{
for(i = 0; i < 4; i++)
{
State[i][j] = AesiSbox[State[i][j]];
//因为 16 * (State[i][j] >> 4) + State[i][j] & 0x0f = State[i][j]
}
}
}

/****行移位函数****/

// 行移位是一个简单的左循环移位操作。当密钥长度为128比特时,状态矩阵的第0行左移0字节,第1行左移1字节,第2行左移2字节,第3行左移3字节
void ShiftRows(void)
{
unsigned char temp[4 * 4];
int i, j;
for(j = 0; j < 4; j++)
{
for(i = 0; i < 4; i++)
{
temp[4 * i + j] = State[i][j];
}
}

for(i = 1; i < 4; i++)
{
for(j = 0; j < 4; j++)
{
if(i == 1)State[i][j] = temp[4 * i + (j + 1) % 4]; //第一行左移1位
else if(i == 2)State[i][j] = temp[4 * i + (j + 2) % 4]; //第二行左移2位
else if(i == 3)State[i][j] = temp[4 * i + (j + 3) % 4]; //第三行左移3位
}
}
}

/****逆行移位函数****/

// 逆行移位是一个简单的右循环移位操作。当密钥长度为128比特时,状态矩阵的第0行右移0字节,第1行右移1字节,第2行右移2字节,第3行右移3字节
void InvShiftRows(void)
{
unsigned char temp[4 * 4];
int i, j;

for(j = 0; j < 4; j++)
{
for(i = 0; i < 4; i++)
{
temp[4 * i + j] = State[i][j];
}
}

for(i = 1; i < 4; i++)
{
for(j = 0; j < 4; j++)
{
if(i == 1)State[i][j] = temp[4 * i + (j + 3) % 4]; //第一行右移1位 j-1+4=j+3
else if(i == 2)State[i][j] = temp[4 * i + (j + 2) % 4]; //第二行右移2位 j-2+4=j+2
else if(i == 3)State[i][j] = temp[4 * i + (j + 1) % 4]; //第三行右移3位 j-3+4=j+2
}
}
}


/****列混合变换函数*****/

// 列混合变换是通过矩阵相乘来实现的,经行移位后的状态矩阵与固定的矩阵相乘,得到混淆后的状态矩阵
void MixColumns(void)
{
unsigned char temp[4 * 4];
int i, j;

for(j = 0; j < 4; j++)
{
for(i = 0; i < 4; i++)
{
temp[4 * i + j] = State[i][j];
}
}
for(j = 0; j < 4; j++)
{
State[0][j] = (unsigned char) ((int)gfmultby02(temp[0 + j]) ^ (int)gfmultby03(temp[4 * 1 + j]) ^
(int)gfmultby01(temp[4 * 2 + j]) ^ (int)gfmultby01(temp[4 * 3 + j]) );
State[1][j] = (unsigned char) ((int)gfmultby01(temp[0 + j]) ^ (int)gfmultby02(temp[4 * 1 + j]) ^
(int)gfmultby03(temp[4 * 2 + j]) ^ (int)gfmultby01(temp[4 * 3 + j]) );
State[2][j] = (unsigned char) ((int)gfmultby01(temp[0 + j]) ^ (int)gfmultby01(temp[4 * 1 + j]) ^
(int)gfmultby02(temp[4 * 2 + j]) ^ (int)gfmultby03(temp[4 * 3 + j]) );
State[3][j] = (unsigned char) ((int)gfmultby03(temp[0 + j]) ^ (int)gfmultby01(temp[4 * 1 + j]) ^
(int)gfmultby01(temp[4 * 2 + j]) ^ (int)gfmultby02(temp[4 * 3 + j]) );
}
}

/****逆列混合变换函数*****/

// 逆变换矩阵同正变换矩阵的乘积恰好为单位矩阵
void InvMixColumns(void)
{
unsigned char temp[4 * 4];
int i, j;

for(i = 0; i < 4; i++)
{
for(j = 0; j < 4; j++)
{
temp[4 * i + j] = State[i][j];
}
}

for (j = 0; j < 4; j++)
{
State[0][j] = (unsigned char) ( (int)gfmultby0e(temp[j]) ^ (int)gfmultby0b(temp[4 + j]) ^
(int)gfmultby0d(temp[4 * 2 + j]) ^ (int)gfmultby09(temp[4 * 3 + j]) );
State[1][j] = (unsigned char) ( (int)gfmultby09(temp[j]) ^ (int)gfmultby0e(temp[4 + j]) ^
(int)gfmultby0b(temp[4 * 2 + j]) ^ (int)gfmultby0d(temp[4 * 3 + j]) );
State[2][j] = (unsigned char) ( (int)gfmultby0d(temp[j]) ^ (int)gfmultby09(temp[4 + j]) ^
(int)gfmultby0e(temp[4 * 2 + j]) ^ (int)gfmultby0b(temp[4 * 3 + j]) );
State[3][j] = (unsigned char) ( (int)gfmultby0b(temp[j]) ^ (int)gfmultby0d(temp[4 + j]) ^
(int)gfmultby09(temp[4 * 2 + j]) ^ (int)gfmultby0e(temp[4 * 3 + j]) );
}
}

unsigned char gfmultby01(unsigned char b)
{
return b;
}

unsigned char gfmultby02(unsigned char b)
{
if(b < 0x80)
return (unsigned char)(int)(b << 1);
else
return (unsigned char)((int)(b << 1) ^ (int)(0x1b));
}

unsigned char gfmultby03(unsigned char b)
{
return (unsigned char) ((int)gfmultby02(b) ^ (int)b);
}

unsigned char gfmultby09(unsigned char b)
{
return (unsigned char)((int)gfmultby02(gfmultby02(gfmultby02(b))) ^ (int)b );
}

unsigned char gfmultby0b(unsigned char b)
{
return (unsigned char)((int)gfmultby02(gfmultby02(gfmultby02(b))) ^
(int)gfmultby02(b) ^ (int)b );
}

unsigned char gfmultby0d(unsigned char b)
{
return (unsigned char)((int)gfmultby02(gfmultby02(gfmultby02(b))) ^
(int)gfmultby02(gfmultby02(b)) ^ (int)(b) );
}

unsigned char gfmultby0e(unsigned char b)
{
return (unsigned char)((int)gfmultby02(gfmultby02(gfmultby02(b))) ^
(int)gfmultby02(gfmultby02(b)) ^(int)gfmultby02(b) );
}


//------------------------------------------------------------------------------------------------------------
// 函数名称:AES_Init
//
// 函数描述:初始化AES 密钥,密钥用于加密解密
//
// 调用参数:keysize 待加解密文长度(单位:字节) keyBytes: 待加解密文
//
// 返回数值:无
//------------------------------------------------------------------------------------------------------------
void AES_Init(int keysize, unsigned char* keyBytes)
{
SetNbNkNr(keysize); //设置密钥长度,轮数
memcpy(key, keyBytes, keysize); //字符串拷贝函数,把keyBytes的keysize个字符复制到key中
KeyExpansion(); //密钥扩展,必须提前做的初始化
}


//------------------------------------------------------------------------------------------------------------
// 函数名称:OnAesEncrypt
//
// 函数描述:用AES加密算法加密数据
//
// 调用参数:InBuffer: 待加密明文,InLength:待加密明文的长度, OutBuffer:加密后的密文
//
// 返回数值:加密后的数据大小 ,错误返回值 0
//------------------------------------------------------------------------------------------------------------

DWORD OnAesEncrypt(LPVOID InBuffer, DWORD InLength, LPVOID OutBuffer)
{
DWORD OutLength = 0;
long j;
long i;

UCHAR *lpCurInBuff = (UCHAR *)InBuffer; // 输入的明文
UCHAR *lpCurOutBuff = (UCHAR *)OutBuffer; // 输出的密文
long blocknum = InLength / 16;
long leftnum = InLength % 16;

UCHAR iv[20] = AESIV; // 获取初始 IV 向量

/******加密前面能被16字节整除的明文长度******/
for(i = 0; i < blocknum; i++)
{
for(j = 0; j < 16; j++ )
{
lpCurOutBuff[j] = (unsigned char)(lpCurInBuff[j] ^ iv[j]); // 将 明文 与 IV向量 进行异或
}

Cipher(lpCurOutBuff, lpCurOutBuff); // 对处理过的明文进行加密

memcpy(iv, lpCurOutBuff, 16); // 将上一段16字节明文加密后的密文作为下一次加密操作的IV向量

lpCurInBuff+=16;
lpCurOutBuff+=16;
OutLength+=16;
}

/*****填充明文扩展区,再进行加密操作******/

// 情况1:待加密明文长度不能被16整除的部分,以0补足16字节
if(leftnum)
{
UCHAR inbuff[16];
memset(inbuff, 0, 16); // WJ 填充模式:0
memcpy(inbuff, lpCurInBuff, leftnum);

for(j = 0; j < 16; j++ )
{
lpCurOutBuff[j] = (unsigned char)( inbuff[j] ^ iv[j] ); // 将 明文 与 IV向量 进行异或
}

Cipher(lpCurOutBuff, lpCurOutBuff); // Aes加密

lpCurOutBuff+=16;
OutLength+=16;
}

// 情况2:待加密明文长度能被16整除,直接新增16个字节,填充值为0
else
{
//新增16个字节,用以确定增加的字节数
UCHAR extrabuff[16];
memset(extrabuff, 0, 16); // WJ 填充模式:0 2022/5/18

for(j = 0; j < 16; j++ )
{
lpCurOutBuff[j] = (unsigned char)( extrabuff[j] ^ iv[j] ); // 将 明文 与 IV向量 进行异或
}

Cipher(lpCurOutBuff, lpCurOutBuff); // Aes加密

OutLength+=16;
}

return OutLength; // 输出加密后的密文长度
}



//------------------------------------------------------------------------------------------------------------
// 函数名称:OnAesUncrypt
//
// 函数描述:用AES加密算法解密数据
//
// 调用参数:InBuffer: 待解密密文,InLength:待解密密文的长度, OutBuffer:解密后的明文
//
// 返回数值:解密后的数据大小 ,错误返回值 0
//------------------------------------------------------------------------------------------------------------
DWORD OnAesUncrypt(LPVOID InBuffer, DWORD InLength, LPVOID OutBuffer)
{
DWORD OutLength = 0;
long blocknum = InLength / 16;
long leftnum = InLength % 16;
long j;
long i;
// unsigned char temp[16];
UCHAR iv[20] = AESIV; // 获取初始 IV 向量

UCHAR *lpCurInBuff = (UCHAR *)InBuffer;
UCHAR *lpCurOutBuff = (UCHAR *)OutBuffer;

// 密文长度必须为16的倍数,否则解密失败
if(leftnum)
{
return 0;
}

/******循环blocknum次,每次解密16字节长度的密文******/
for(i = 0; i < blocknum; i++)
{
InvCipher(lpCurInBuff, lpCurOutBuff); // Aes解密

for(j = 0; j < 16; j++ )
{
lpCurOutBuff[j] = (unsigned char)(lpCurOutBuff[j] ^ iv[j]); // 将 密文 与 IV向量 进行异或
}

memcpy(iv, lpCurInBuff, 16); // 将上一段16字节解密前的密文作为下一次解密操作的IV向量

lpCurInBuff+=16;
lpCurOutBuff+=16;
OutLength+=16;
}

return OutLength;
}
main.cpp
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
#include <cstdint>
#include <iostream>
#include <string>
#include "AES.h"

using namespace std;
uint8_t InBuff[1024];
uint8_t OutBuff[1024];

uint16_t AesLen_Byte;

uint16_t OutLength;
const int BUF_SIZE=1024;
char sendBuf[BUF_SIZE];//发送缓冲区
char inputBuf[BUF_SIZE]={};
int main()
{
uint8_t i = 0;
//std::string msg;
//std::cin>>msg;
//char FileBuff[ msg.length()+1];
cin.getline(inputBuf, 1024, '\n');
strcpy(sendBuf, inputBuf);
cout<<"changdu:"<<strlen(sendBuf)<<endl;
/*
msg.copy(FileBuff, msg.length(), 0);//这里5代表复制几个字符,0代表复制的位置,
*(FileBuff+msg.length())='\0';//注意手动加结束符!!!
*/
std::string AESKEY="IMNKUPSL20011227";
AES_Init(16, (unsigned char*)AESKEY.c_str()); // 设置AES密钥长度为4 * 4 = 16字节(16 * 8 = 128位) ,密钥初始值为 AESKEY


//加密

OutLength = OnAesEncrypt(sendBuf, strlen(sendBuf), OutBuff);
cout<<"changdu:"<<strlen(sendBuf)<<endl;
cout<<"changduhou:"<<OutLength<<endl;

printf("加密后: ");

for(i = 0; i < OutLength; i++)
{
printf(" %02x ", OutBuff[i]);
}
std::cout<<std::endl;
//解密
cout<<"输出:"<<OutBuff;
memcpy(InBuff, OutBuff, OutLength);

OutLength = OnAesUncrypt(InBuff, OutLength, OutBuff);

printf("解密后:");
for(i = 0; i < OutLength; i++)
{
printf("%s", OutBuff[i]);
}
}

RSA代码

考虑到大多数人都是抄袭的16级信安法巨神周子祎流传下来的代码(赵梓杰抄的那份),那希望大家看懂,原理去看他们的报告即可。 注意,需要自己封装一下。

下面给出我对于RSA的一些封装工作,如下所示

BigInt.h
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
#pragma once
#include <iostream>

using namespace std;


//存放一些已知的素数,用于之后的初步检测
static int prime[] = { 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,
37, 41, 43, 47, 53, 59, 61, 67, 71, 73,
79, 83, 89, 97, 101, 103, 107, 109, 113, 127,
131, 137, 139, 149, 151, 157, 163, 167, 173, 179,
181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
293, 307, 311, 313, 317, 331, 337, 347, 349, 353,
359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
421, 431, 433, 439, 443, 449, 457, 461, 463, 467,
479, 487, 491, 499, 503, 509, 521, 523, 541, 547,
557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
613, 617, 619, 631, 641, 643, 647, 653, 659, 661,
673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
821, 823, 827, 829, 839, 853, 857, 859, 863, 877,
881, 883, 887, 907, 911, 919, 929, 937, 941, 947,
953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019,
1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153,
1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229,
1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291, 1297,
1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381,
1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453,
1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523,
1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583, 1597,
1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663,
1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741,
1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823,
1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901,
1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993,
1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063,
2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131,
2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213, 2221,
2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293,
2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371,
2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423, 2437,
2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531, 2539,
2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621,
2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689,
2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741, 2749,
2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819, 2833,
2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903, 2909,
2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999, 3001,
3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083,
3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187,
3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257, 3259,
3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331, 3343,
3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433,
3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517,
3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571, 3581,
3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643, 3659,
3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733,
3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823,
3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907, 3911,
3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989, 4001,
4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073,
4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153,
4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231, 4241,
4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297, 4327,
4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421,
4423, 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507,
4513, 4517, 4519, 4523, 4547, 4549, 4561, 4567, 4583, 4591,
4597, 4603, 4621, 4637, 4639, 4643, 4649, 4651, 4657, 4663,
4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759,
4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861,
4871, 4877, 4889, 4903, 4909, 4919, 4931, 4933, 4937, 4943,
4951, 4957, 4967, 4969, 4973, 4987, 4993, 4999 , 5003, 5009,
5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099,
5101, 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189,
5197, 5209, 5227, 5231, 5233, 5237, 5261, 5273, 5279, 5281,
5297, 5303, 5309, 5323, 5333, 5347, 5351, 5381, 5387, 5393,
5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449,
5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527,
5531, 5557, 5563, 5569, 5573, 5581, 5591, 5623, 5639, 5641,
5647, 5651, 5653, 5657, 5659, 5669, 5683, 5689, 5693, 5701,
5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791, 5801,
5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861,
5867, 5869, 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953,
5981, 5987, 6007, 6011, 6029, 6037, 6043, 6047, 6053, 6067,
6073, 6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133, 6143,
6151, 6163, 6173, 6197, 6199, 6203, 6211, 6217, 6221, 6229,
6247, 6257, 6263, 6269, 6271, 6277, 6287, 6299, 6301, 6311,
6317, 6323, 6329, 6337, 6343, 6353, 6359, 6361, 6367, 6373,
6379, 6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473, 6481,
6491, 6521, 6529, 6547, 6551, 6553, 6563, 6569, 6571, 6577,
6581, 6599, 6607, 6619, 6637, 6653, 6659, 6661, 6673, 6679,
6689, 6691, 6701, 6703, 6709, 6719, 6733, 6737, 6761, 6763,
6779, 6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833, 6841,
6857, 6863, 6869, 6871, 6883, 6899, 6907, 6911, 6917, 6947,
6949, 6959, 6961, 6967, 6971, 6977, 6983, 6991, 6997, 7001,
7013, 7019, 7027, 7039, 7043, 7057, 7069, 7079, 7103, 7109,
7121, 7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207, 7211,
7213, 7219, 7229, 7237, 7243, 7247, 7253, 7283, 7297, 7307,
7309, 7321, 7331, 7333, 7349, 7351, 7369, 7393, 7411, 7417,
7433, 7451, 7457, 7459, 7477, 7481, 7487, 7489, 7499, 7507,
7517, 7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561, 7573,
7577, 7583, 7589, 7591, 7603, 7607, 7621, 7639, 7643, 7649,
7669, 7673, 7681, 7687, 7691, 7699, 7703, 7717, 7723, 7727,
7741, 7753, 7757, 7759, 7789, 7793, 7817, 7823, 7829, 7841,
7853, 7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919, 7927,
7933, 7937, 7949, 7951, 7963, 7993, 8009, 8011, 8017, 8039,
8053, 8059, 8069, 8081, 8087, 8089, 8093, 8101, 8111, 8117,
8123, 8147, 8161, 8167, 8171, 8179, 8191, 8209, 8219, 8221,
8231, 8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291, 8293,
8297, 8311, 8317, 8329, 8353, 8363, 8369, 8377, 8387, 8389,
8419, 8423, 8429, 8431, 8443, 8447, 8461, 8467, 8501, 8513,
8521, 8527, 8537, 8539, 8543, 8563, 8573, 8581, 8597, 8599,
8609, 8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677, 8681,
8689, 8693, 8699, 8707, 8713, 8719, 8731, 8737, 8741, 8747,
8753, 8761, 8779, 8783, 8803, 8807, 8819, 8821, 8831, 8837,
8839, 8849, 8861, 8863, 8867, 8887, 8893, 8923, 8929, 8933,
8941, 8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011, 9013,
9029, 9041, 9043, 9049, 9059, 9067, 9091, 9103, 9109, 9127,
9133, 9137, 9151, 9157, 9161, 9173, 9181, 9187, 9199, 9203,
9209, 9221, 9227, 9239, 9241, 9257, 9277, 9281, 9283, 9293,
9311, 9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377, 9391,
9397, 9403, 9413, 9419, 9421, 9431, 9433, 9437, 9439, 9461,
9463, 9467, 9473, 9479, 9491, 9497, 9511, 9521, 9533, 9539,
9547, 9551, 9587, 9601, 9613, 9619, 9623, 9629, 9631, 9643,
9649, 9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733, 9739,
9743, 9749, 9767, 9769, 9781, 9787, 9791, 9803, 9811, 9817,
9829, 9833, 9839, 9851, 9857, 9859, 9871, 9883, 9887, 9901,
9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973, 10007,10009 };

static const int BIsize = 64;

class BigInt {
// 重载运算符
friend BigInt operator+ (const BigInt&, const BigInt&);
friend BigInt operator- (const BigInt&, const BigInt&);
friend BigInt operator- (const BigInt&, const int&);
friend BigInt operator* (const BigInt&, const BigInt&);
friend BigInt operator% (const BigInt&, const BigInt&);
friend BigInt operator/ (const BigInt&, const BigInt&);
friend BigInt operator* (const BigInt&, const unsigned int&);
friend bool operator< (const BigInt&, const BigInt&);
friend bool operator> (const BigInt&, const BigInt&);
friend bool operator<= (const BigInt&, const int&);
friend bool operator== (const BigInt&, const BigInt&);
friend bool operator== (const BigInt&, const int&);
friend ostream& operator<< (ostream&, const BigInt&);
friend istream& operator>> (istream&, BigInt&);
friend BigInt PowerMode(const BigInt&, const BigInt&, const BigInt&);
friend void SortPrime(BigInt& n);
public:
BigInt();
BigInt(const int&);
BigInt(const BigInt&);

// 赋值
void operator= (const BigInt&);
void operator= (const int& a) { Clear(); data[0] = a; }
void operator>> (const int&);

// 辅助函数
inline int GetLenth() const; //返回大数的长度
bool TestSign() { return sign; } //判断大数的正负
void Clear(); //大数清0
void Random(); //随机产生一个大数
void RandomSmall(); //随机产生一个稍小的大数
void display() const; // 输出
void Output(ostream& out) const;
bool IsOdd() const { return (data[0] & 1); } //判断大数奇偶性
int ToInt(){return data[0];}
string ToHex(); // BigInt转十六进制表示
private:
unsigned int data[BIsize]; // 数据
bool sign; // 符号
};

BigInt operator+ (const BigInt&, const BigInt&);
BigInt operator- (const BigInt&, const BigInt&);
BigInt operator- (const BigInt&, const int&);
BigInt operator* (const BigInt&, const BigInt&);
BigInt operator/ (const BigInt&, const BigInt&);
BigInt operator% (const BigInt&, const BigInt&);
BigInt operator* (const BigInt&, const unsigned int&);
BigInt PowerMode(const BigInt&, const BigInt&, const BigInt&);
bool operator< (const BigInt&, const BigInt&);
bool operator> (const BigInt&, const BigInt&);
bool operator<= (const BigInt&, const int&);
bool operator== (const BigInt&, const BigInt&);
bool operator== (const BigInt&, const int&);
ostream& operator<< (ostream&, const BigInt&);
istream& operator>>(istream&,BigInt &);
void SortPrime(BigInt& n);
BigIntdata.cpp
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
#pragma once
#include<stdlib.h>
#include"BigInt.h"

using namespace std;

// BigInt清零
void BigInt::Clear()
{
for (int i = 0; i < BIsize; i++)
data[i] = 0;
}

// 产生一个随机大数,LENTH为SIZE的1/4
void BigInt::Random()
{
for (int i = 0; i<(BIsize / 4); i++)
//由于RAND()最大只能产生0X7FFF的数,为了能产生32位的随机数,需要
//3次RAND()操作
data[i] = (rand() << 17) + (rand() << 2) + rand() % 4;

}

// 产生一个较小的随机大数,大数的LENGTH为SIZE的1/8
void BigInt::RandomSmall()
{
for (int i = 0; i < (BIsize / 16); i++)
data[i] = (rand() << 17) + (rand() << 2) + rand() % 4; // 通过3次rand()产生32位随机数
}

// BigInt转16进制后输出
void BigInt::display() const
{
unsigned int temp, result;
unsigned int tempAnd = 0xf0000000;

for (int i = GetLenth() - 1; i >= 0; i--)
{
temp = data[i];
for (int j = 0; j < 8; j++)
{
result = temp & tempAnd;
result = (result >> 28);
temp = (temp << 4);
switch (result)
{
case 10:cout << "A";break;
case 11:cout << "B";break;
case 12:cout << "C";break;
case 13:cout << "D";break;
case 14:cout << "E";break;
case 15:cout << "F";break;
default:cout<<result;break;
}
}
cout << " ";
if (i == GetLenth() / 2)
cout << endl;
}
cout << endl;
}

// BigInt转16进制存放在string中
string BigInt::ToHex()
{
unsigned int temp, result;
unsigned int tempAnd = 0xf0000000;
string hex="";

for (int i = GetLenth() - 1; i >= 0; i--)
{
temp = data[i];
for (int j = 0; j < 8; j++)
{
result = temp & tempAnd;
result = (result >> 28);
temp = (temp << 4);
char val;
switch (result)
{
case 0:val='0';break;
case 1:val='1';break;
case 2:val='2';break;
case 3:val='3';break;
case 4:val='4';break;
case 5:val='5';break;
case 6:val='6';break;
case 7:val='7';break;
case 8:val='8';break;
case 9:val='9';break;
case 10:val='A';break;
case 11:val= 'B';break;
case 12:val= 'C';break;
case 13:val= 'D';break;
case 14:val= 'E';break;
case 15:val= 'F';break;
default:cout<<result;break;
}
hex+=val;
}
}
return hex;
}
BigIntcal.cpp
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
#pragma once
#include <stdlib.h>
#include "BigInt.h"
using namespace std;

// 竖式相加法实现BigInt求和
BigInt operator+ (const BigInt& a, const BigInt& b)
{
BigInt result;
unsigned __int64 sum; // 64位数据,存放每两位数相加的临时和
unsigned int carry = 0; // 进位标志
unsigned int sub; // 两数符号相异,时存放每两位数相减的临时差

int length = (a.GetLenth() >= b.GetLenth() ? a.GetLenth() : b.GetLenth());

// 当两数符号相同时,进行加法运算
if (a.sign == b.sign)
{
// 每一位进行竖式相加
for (int i = 0; i < length; i++)
{
sum = (unsigned __int64)a.data[i] + b.data[i] + carry;
result.data[i] = (unsigned int)sum;
// sum的高位为进位
carry = (sum >> 32);
}

result.sign = a.sign;
return result;
}
else // 两数符号不同时,进行减法运算
{
BigInt tempa, tempb;

//取出a,b中绝对值较大的作为被减数
if (a < b)
{
tempa = b;
tempb = a;
}
else
{
tempa = a;
tempb = b;
}

//每一位进行竖式减
for (int i = 0; i < length; i++)
{
sub = tempb.data[i] + carry;
if (tempa.data[i] >= sub)
{
result.data[i] = tempa.data[i] - sub;
carry = 0;
}
else
{
//借位减
result.data[i] = (unsigned __int64)tempa.data[i] + (1 << 32) - sub;
carry = 1;
}
}
result.sign = tempa.sign;
return result;
}
}

// 竖式相减法BigInt求差
BigInt operator- (const BigInt& a, const BigInt& b)
{
BigInt result;
unsigned __int64 sum; // 存放每两位数相加的临时和
unsigned int carry = 0; // 进位标志
unsigned int sub; // 两数符号相异时存放每两位数相减的临时差

//符号相同时,进行减法运算
if (a.sign == b.sign)
{
BigInt tempa, tempb;

//取出a,b中绝对值较大的作为被减数
if (a < b)
{
tempa = b;
tempb = a;
tempa.sign = !tempa.sign;
}
else
{
tempa = a;
tempb = b;
}

// 每一位进行竖式减
for (int i = 0; i < BIsize; i++)
{
sub = tempb.data[i] + carry;
if (tempa.data[i] >= sub)
{
result.data[i] = tempa.data[i] - sub;
carry = 0;
}
else
{
// 借位减
result.data[i] = (unsigned __int64)tempa.data[i] + (1 << 32) - sub;
carry = 1;
}
}
result.sign = tempa.sign;
return result;
}
else // 两数符号不同时,进行加法运算
{
// 每一位进行竖式相加
for (int i = 0; i < BIsize; i++)
{
sum = (unsigned __int64)a.data[i] + b.data[i] + carry;
result.data[i] = (unsigned int)sum;
// sum的高位为进位
carry = (sum >> 32);
}
result.sign = a.sign;
return result;
}
}

// BigInt - Int
BigInt operator- (const BigInt& a, const int& b)
{
BigInt temp(b);
BigInt result = a - temp;
return result;
}

// BigInt * Int
BigInt operator* (const BigInt& a, const unsigned int& b)
{
BigInt result; // B乘以A的每一位的临时积
unsigned __int64 sum; // 进位
unsigned int carry = 0;

for (int i = 0; i < BIsize; i++)
{
sum = ((unsigned __int64)a.data[i]) * b + carry;
result.data[i] = (unsigned int)sum;
// 进位在SUM的高位中
carry = (sum >> 32);
}
result.sign = a.sign;
return result;
}

// 竖式相乘求BigInt乘积
BigInt operator* (const BigInt& a, const BigInt& b)
{
// last存放竖式上一行的积,temp存放当前行的积
BigInt result, last, temp;
// sum存放当前行带进位的积
unsigned __int64 sum;
// 存放进位
unsigned int carry;

// 进行竖式乘
for (int i = 0; i < b.GetLenth(); i++)
{
carry = 0;
// B的每一位与A相乘
for (int j = 0; j < a.GetLenth() + 1; j++)
{
sum = ((unsigned __int64)a.data[j]) * (b.data[i]) + carry;
if ((i + j) < BIsize)
temp.data[i + j] = (unsigned int)sum;
carry = (sum >> 32);
}
result = (temp + last);
last = result;
temp.Clear();
}

// 判断积的符号
result.sign=(a.sign==b.sign);
return result;
}

// BigInt除法,采用试商除法+二分查找法
BigInt operator/ (const BigInt& a, const BigInt& b)
{
// mul为当前试商,low,high为二分查找试商时所用的标志
unsigned int mul, low, high;
// sub为除数与当前试商的积,subsequent为除数与下一试商的积
// dividend存放临时被除数
BigInt dividend, quotient, sub, subsequent;
int lengtha = a.GetLenth(), lengthb = b.GetLenth();

//如果被除数小于除数,返回0
if (a < b)
{
quotient.sign =(a.sign == b.sign);
return quotient;
}

// 把被除数按除数的长度从高位截位
int i;
for (i = 0; i < lengthb; i++)
dividend.data[i] = a.data[lengtha - lengthb + i];

for (i = lengtha - lengthb; i >= 0; i--)
{
//如果被除数小于除数,再往后补位
if (dividend < b)
{
for (int j = lengthb; j > 0; j--)
dividend.data[j] = dividend.data[j - 1];
dividend.data[0] = a.data[i - 1];
continue;
}

low = 0;
high = 0xffffffff;

// 二分查找法查找试商
while (low < high)
{
mul = (((unsigned __int64)high) + low) / 2;
sub = (b * mul);
subsequent = (b * (mul + 1));

if (((sub < dividend) && (subsequent > dividend)) || (sub == dividend))
break;

if (subsequent == dividend)
{
mul++;
sub = subsequent;
break;
}

if ((sub < dividend) && (subsequent < dividend))
{
low = mul;
continue;
}

if ((sub > dividend) && (subsequent > dividend))
{
high = mul;
continue;
}

}

// 试商结果保存到商中去
quotient.data[i] = mul;
// 临时被除数变为被除数与试商积的差
dividend = dividend - sub;

// 临时被除数往后补位
if ((i - 1) >= 0)
{
for (int j = lengthb; j > 0; j--)
dividend.data[j] = dividend.data[j - 1];
dividend.data[0] = a.data[i - 1];
}
}

// 判断商的符号
quotient.sign = (a.sign == b.sign);
return quotient;
}

// BigInt求模,与除法类似
BigInt operator% (const BigInt& a, const BigInt& b)
{
unsigned int mul, low, high;
BigInt dividend, quotient, sub, subsequent;
int lengtha = a.GetLenth(), lengthb = b.GetLenth();

// 如果被除数小于除数,返回被除数为模
if (a < b)
{
dividend = a;
// 余数的商永远与被除数相同
dividend.sign = a.sign;
return dividend;
}

// 进行除法运算
int i;
for (i = 0; i < lengthb; i++)
dividend.data[i] = a.data[lengtha - lengthb + i];

for (i = lengtha - lengthb; i >= 0; i--)
{
if (dividend < b)
{
for (int j = lengthb; j > 0; j--)
dividend.data[j] = dividend.data[j - 1];
dividend.data[0] = a.data[i - 1];
continue;
}

low = 0;
high = 0xffffffff;

while (low <= high)
{
mul = (((unsigned __int64)high) + low) / 2;
sub = (b * mul);
subsequent = (b * (mul + 1));

if (((sub < dividend) && (subsequent > dividend)) || (sub == dividend))
break;

if (subsequent == dividend)
{
mul++;
sub = subsequent;
break;
}

if ((sub < dividend) && (subsequent < dividend))
{
low = mul;
continue;
}

if ((sub > dividend) && (subsequent > dividend))
{
high = mul;
continue;
}
}

quotient.data[i] = mul;
dividend = dividend - sub;
if ((i - 1) >= 0)
{
for (int j = lengthb; j > 0; j--)
dividend.data[j] = dividend.data[j - 1];
dividend.data[0] = a.data[i - 1];
}
}

//临时被除数即为所求模
dividend.sign = a.sign;
return dividend;
}

// 模幂运算——计算n的p次幂模m
// 利用Montgomery算法,
BigInt PowerMode(const BigInt &n, const BigInt &p, const BigInt &m)
{
BigInt temp = p;
BigInt base = n % m;
BigInt result(1);

//检测指数p的二进制形式的每一位
while (!(temp <= 1))
{
//如果该位为1,则表示该位需要参与模运算
if (temp.IsOdd())
result = (result * base) % m;
base = (base * base) % m;
temp >> 1;
}
return (base * result) % m;
}
BigIntop.cpp
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
#pragma once
#include <stdlib.h>
#include "BigInt.h"
using namespace std;

// 初始化BigInt
BigInt::BigInt()
{
for (int i = 0; i < BIsize; i++)
data[i] = 0;
sign = true;
}
BigInt::BigInt(const int &input)
{
for (int i = 0; i < BIsize; i++)
data[i] = 0;
data[0] = input;
if (input >= 0)
sign = true;
else
sign = false;
}
BigInt::BigInt(const BigInt &input)
{
for (int i = 0; i < BIsize; i++)
data[i] = input.data[i];
sign = input.sign;
}

// 赋值
void BigInt::operator=(const BigInt &input)
{
for (int i = 0; i < BIsize; i++)
data[i] = input.data[i];
sign = input.sign;
}

// 比较
bool operator<(const BigInt &a, const BigInt &b)
{
for (int i = BIsize - 1; i > 0; i--)
{
if (a.data[i] < b.data[i])
return true;
if (a.data[i] > b.data[i])
return false;
}
return a.data[0] < b.data[0];
}
bool operator>(const BigInt &a, const BigInt &b)
{
for (int i = BIsize - 1; i >= 0; i--)
{
if (a.data[i] > b.data[i])
return true;
if (a.data[i] < b.data[i])
return false;
}
return false;
}
bool operator<=(const BigInt &a, const int &b)
{
for (int i = 1; i < a.GetLenth(); i++)
{
if (a.data[i] != 0)
return false;
}
return (a.data[0] <= b);
}

// 相等判断(!=也可用==结果判断
bool operator==(const BigInt &a, const BigInt &b)
{
for (int i = 0; i < BIsize; i++)
if (a.data[i] != b.data[i])
return false;
return true;
}
bool operator==(const BigInt &a, const int &b)
{
for (int i = 1; i < a.GetLenth(); i++)
if (a.data[i] != 0)
return false;
return a.data[0] == b;
}

// 重载输出运算符,实现文件写BigInt
void BigInt::Output(ostream &out) const
{
unsigned int temp, result;
unsigned int tempAnd = 0xf0000000;

for (int i = GetLenth() - 1; i >= 0; i--)
{
temp = data[i];
for (int j = 0; j < 8; j++)
{
result = temp & tempAnd;
result = (result >> 28);
temp = (temp << 4);
switch (result)
{
case 10:out << "A";break;
case 11:out << "B";break;
case 12:out << "C";break;
case 13:out << "D";break;
case 14:out << "E";break;
case 15:out << "F";break;
default:out << result;break;
}
}
}
out << endl;
}
ostream &operator<<(ostream &out, const BigInt &num)
{
num.Output(out);
return out;
}

// 重载输入运算符,实现从文件中读BigInt
istream &operator>>(istream &in, BigInt &num)
{
num=0;
char temp;
in.get(temp);
while(temp!='\n')
{
int val;
// 16进制转十进制
switch (temp)
{
case '0':val=0;break;
case '1':val=1;break;
case '2':val=2;break;
case '3':val=3;break;
case '4':val=4;break;
case '5':val=5;break;
case '6':val=6;break;
case '7':val=7;break;
case '8':val=8;break;
case '9':val=9;break;
case 'A':val=10;break;
case 'B':val=11;break;
case 'C':val=12;break;
case 'D':val=13;break;
case 'E':val=14;break;
case 'F':val=15;break;
}
num = num * 16 + val; // 累加求值
in.get(temp);
}
return in;
}

// 返回data中不为0的位数
inline int BigInt::GetLenth() const
{
int lenth = BIsize;
for (int i = BIsize - 1; i >= 0; i--)
{
//第一位不为0即为LENGTH
if (data[i] == 0)
lenth--;
else
break;
}
return lenth;
}

// 重载移位操作符,向右移N位
void BigInt::operator>>(const int &a)
{
unsigned int bit;
data[0] = (data[0] >> a);
for (int i = 1; i < GetLenth(); i++)
{
// 先将每一位的低位移到BIT中
bit = data[i] & 1;
// 再把BIT移到上一位的高位中
bit = bit << (32 - a);
data[i - 1] = data[i - 1] | bit;
data[i] = (data[i] >> a);
}
}
genPrime.h
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
#pragma once
#include <iostream>
#include "BigInt.h"
using namespace std;

//对大奇数n进行RabinMiller检测
bool RabinMiller(const BigInt& n)
{
BigInt r, a, y;
unsigned int s, j;
r = n - 1;
s = 0;

while (!r.IsOdd())
{
s++;
r >> 1;
}

//随机产生一个小于N-1的检测数a
a.Randomsmall();

//y = a的r次幂模n
y = PowerMode(a, r, n);

//检测J=2至J<S轮
if ((!(y == 1)) && (!(y == (n - 1))))
{
j = 1;
while ((j <= s - 1) && (!(y == (n - 1))))
{
y = (y*y) % n;
if (y == 1)
return false;
j++;
}
if (!(y == (n - 1)))
return false;
}
return true;
}

//产生一个素数
BigInt GeneratePrime(int &time)
{
BigInt n;
int i = 0;

//无限次循环,不断产生素数,直到i==5时(通过五轮RabinMiller测试)才会跳出while循环
while (i < 5)
{
//记录生成了多少次大奇数
time++;

//产生一个待测素数
cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
cout << "产生待测大奇数:" << endl;
SortPrime(n);
n.display();

i = 0;
//进行五轮RABINMILLER测试,五轮全部通过则素数合格
for (; i < 5; i++)
{
cout << "正在进行第" << i + 1 << "轮RabinMiller测试:";
if (!RabinMiller(n))
{
cout << "…………测试失败" << endl<< endl;
break;
}
cout << "…………测试通过" << endl << endl;
}
}
return n;
}

//求两个大数的最大公约数,采用辗转相除法
BigInt Gcd(const BigInt& m, const BigInt& n)
{
if (n == 0)
return m;
else
return Gcd(n, m%n);
}

//用扩展欧几里德算法求乘法模逆
BigInt ExtendedGcd(const BigInt& a, const BigInt& b, BigInt& x, BigInt& y)
{
BigInt t, d;
//如果一个操作数为零则无法进行除法运算
if (b == 0)
{
x = 1;
y = 0;
return a;
}
d = ExtendedGcd(b, a%b, x, y);
t = x;
x = y;
y = t - ((a / b)*y);
return d;
}
rsa.h
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
#ifndef RSA_rsa_H
#define RSA_rsa_H
#include "BigInt.h"
#include <iostream>
#include <time.h>
#include <ctime>
#include <fstream>
#include <bitset>
#include <string>
using namespace std;


struct Rsa
{
BigInt n, e, d; // e为公钥,d为私钥
Rsa();
Rsa(BigInt& N, BigInt& E);
Rsa(BigInt& N, BigInt& E, BigInt& D);
};

void SortPrime(BigInt &n);
bool RabinMiller(const BigInt &n);
BigInt GeneratePrime();
BigInt Gcd(const BigInt &m, const BigInt &n);
BigInt ExtendedGcd(const BigInt &a, const BigInt &b, BigInt &x, BigInt &y);
BigInt StringToBigInt(string str);
string BigIntToString(BigInt num);
string BigIntToHex(BigInt &num);
BigInt HexToBigInt(string hex);

#endif //RSA_rsa_H
rsa.cpp
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
#include"rsa.h"

// 产生一个奇数作为待测素数
void SortPrime(BigInt& n)
{
int i = 0;
BigInt divisor;
const int length = sizeof(prime) / sizeof(int);

while (i != length)
{
n.Random();
while (!n.IsOdd())
n.Random();

i = 0;
for (; i < length; i++)
if ((n % prime[i]) == 0)
break;
}
}

// RabinMiller检测某个数是否是素数
bool RabinMiller(const BigInt& n)
{
BigInt r, a, y;
unsigned int s, j;
r = n - 1;
s = 0;

while (!r.IsOdd())
{
s++;
r >> 1;
}

a.RandomSmall(); // 随机产生一个小于N-1的检测数a

y = PowerMode(a, r, n); //y = a的r次幂模n

//检测J=2至J<S轮
if ((!(y == 1)) && (!(y == (n - 1))))
{
j = 1;

while ((j <= s - 1) && (!(y == (n - 1))))
{
y = (y * y) % n;
if (y == 1)
return false;
j++;
}

if (!(y == (n - 1)))
return false;
}
return true;
}

//产生一个素数
BigInt GeneratePrime()
{
srand((unsigned)time(NULL));
BigInt n;
int time = 0; // 记录产生素数次数
bool success=false;

// 循环产生素数,通过5轮RabinMiller测试
while (!success)
{
time++;
//产生一个待测素数
cout << "生成第" << time << "个大奇数:" << endl;
SortPrime(n);
n.display();

//进行五轮RABINMILLER测试,五轮全部通过则素数合格
for (int i=0; i < 5; i++)
{
cout << "第" << i + 1 << "轮RabinMiller测试:";
if (!RabinMiller(n))
{
cout << "Fail.." << endl;
break;
}
cout << "Pass!" << endl;
success=true;
}
cout<<endl;
}
return n;
}

// 辗转相除法求两个大数的最大公约数
BigInt Gcd(const BigInt& m, const BigInt& n)
{
if (n == 0)
return m;
else
return Gcd(n, m % n);
}

// 扩展欧几里德求乘法逆元
BigInt ExtendedGcd(const BigInt& a, const BigInt& b, BigInt& x, BigInt& y)
{
BigInt t, d;

// 如果一个操作数为零则无法进行除法运算
if (b == 0)
{
x = 1;
y = 0;
return a;
}

d = ExtendedGcd(b, a % b, x, y);
t = x;
x = y;
y = t - ((a / b) * y);
return d;
}

BigInt StringToBigInt(string str)
{
BigInt a(0);
for(int i=str.length()-1;i>=0;i--)
{
int x=str[i]+128;
BigInt temp=a*256;
a=temp+x;
}
//cout << "a" << a.GetLenth() << endl;
return a;
}

string BigIntToString(BigInt num)
{
string str="";
while(!(num==0))
{
BigInt temp=num%256;
int x=temp.ToInt();
num=num/256;
str+=(char)(x-128);
}
return str;
}

string BigIntToHex(BigInt &num)
{
return num.ToHex();
}

BigInt HexToBigInt(string hex)
{
BigInt result(0);
for(int i=0;i<hex.length();i++)
{
int val;
switch (hex[i])
{
case '0':val=0;break;
case '1':val=1;break;
case '2':val=2;break;
case '3':val=3;break;
case '4':val=4;break;
case '5':val=5;break;
case '6':val=6;break;
case '7':val=7;break;
case '8':val=8;break;
case '9':val=9;break;
case 'A':val=10;break;
case 'B':val=11;break;
case 'C':val=12;break;
case 'D':val=13;break;
case 'E':val=14;break;
case 'F':val=15;break;
}
result = result * 16 + val;
}
return result;
}

Rsa::Rsa()
{
BigInt p = GeneratePrime();
BigInt q = GeneratePrime();
n = p * q;
BigInt f = (p - 1) * (q - 1);
BigInt x,temp;

// 循环生成e,直到满足条件
while (1)
{
//产生与fn互质的e
e.Random();
while (!(Gcd(e, f) == 1))
e.Random();

//用扩展欧几里德算法试图求出e模t的乘法逆元
temp = ExtendedGcd(e, f, d, x);

// e*d模t结果为1 -> d是e模t的乘法逆元,计算完成
temp = (e * d) % f;
if (temp == 1)
break;
}
}

Rsa::Rsa(BigInt &N, BigInt &E)
{
n=N;
e=E;
}

Rsa::Rsa(BigInt &N, BigInt &E, BigInt &D)
{
n=N;
e=E;
d=D;
}
main.cpp
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
#include <iostream>
#include <iomanip>
#include <chrono>
#include"BigInt.h"
#include"rsa.h"
#include<cstdio>
#include<fstream>
using namespace std;
BigInt RSAEncode(BigInt &m, Rsa &R){return PowerMode(m, R.d, R.n);}
BigInt RSADecode(BigInt &c, Rsa &R){return PowerMode(c, R.e, R.n);}
string try1try() {
BigInt cn, ce, cd;
ifstream openc("ServerRsa.txt");
openc >> cn;
openc >> ce;
openc >> cd;
openc.close();
Rsa ClientRsa(cn, ce, cd); // for encode
string message="20011227IMNKUPSL";
BigInt m = StringToBigInt(message); // message to BigInt
BigInt c = RSAEncode(m, ClientRsa); // encode
string text = BigIntToHex(c); // text to send
cout<<"加密后:"<<text<<endl;
return text;
}
int main()
{
// read RSA keys from txt
BigInt sn, se, sd, cn, ce;
ifstream openc("ServerPk.txt");
ifstream opens("ClientRsa.txt");
openc >> cn;
openc >> ce;
opens >> sn;
opens >> se;
opens >> sd;
openc.close();
opens.close();
Rsa ServerRsa(sn, se, sd); // for encode
Rsa ClientRsa(cn, ce); // for decode
string msg=try1try();
BigInt c = HexToBigInt(msg);
BigInt m = RSADecode(c, ClientRsa);
string message = BigIntToString(m);
cout << "--->Receive from Client: " << endl;
cout << message << endl;
}

其他

唯一需要自己写的地方在于,密码算法大多数只能处理数值,因此需要自己写一些字符串和数值转化的函数。这部分我已经写在rsa里了,如果你上面的代码没好好看的话,可以往上翻翻好好看看。

协议设计

就是用对方的RSA公钥加密自己的AES密钥,再用AES密钥加密消息,然后发送出去。接收方用自己的RSA私钥解密,得到对方的AES密钥,然后用这个AES密钥来解密。

按理说AES密钥应该是随机生成,不过我的程序没有实现。是我提前设定好的。

附上一些有关密钥分发的函数吧。别的就不在此展示了,就是纯纯缝合了。

密钥分发
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
string sendAESkey() {
BigInt cn, ce, cd;
ifstream openc("ClientRsa.txt");
openc >> cn;
openc >> ce;
openc >> cd;
openc.close();
Rsa ClientRsa(cn, ce, cd); // for encode
cout<<"我的AES密钥为:"<<clientAESkey<<endl<<endl;
BigInt m1= StringToBigInt(clientAESkey); // message to BigInt
BigInt c1 = RSAEncode(m1, ClientRsa); // encode
string text = BigIntToHex(c1); // text to send
cout<<"加密后发出的AES密钥:"<<text<<endl<<endl;
return text;
}
string getAESkey(string s) {
BigInt sn, se;
ifstream opens("ServerPk.txt");
opens >> sn;
opens >> se;
opens.close();
Rsa ServerRsa(sn, se); // for decode
BigInt c = HexToBigInt(s);
BigInt m = RSADecode(c, ServerRsa);
string message = BigIntToString(m);
cout<<"解密后对方的AES原文为:"<<message<<endl<<endl;
return message;
}

更多代码见github仓库

关于密码学的所有代码都在这里