code
des:
#include <stdio.h> #include <string.h> #include <iostream> #include <stdlib.h> using namespace std; int IP_Table[64] = { //IP置换矩阵 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}; int E_Table[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}; int P_Table[32] = { // P 盒 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}; int IPR_Table[64] = { //逆IP置换矩阵 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}; // ppt中的置换选择1中的左边和右边矩阵铺成了1维数组 int PC1_Table[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}; int PC2_Table[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}; int S_Box[8][4][16] = { //8个S盒 数组形状取决于前面的[][][], 此处为8个4*16矩阵,每个矩阵代表一个S盒 // S1 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, // S2 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, // S3 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, // S4 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, // S5 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, // S6 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, // S7 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, // S8 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}; // 把CHAR转换为INT // 例如 input:abcdqwer // output:a对应的8位ascii码 b对应的8位ascii码 ... r对应的8位ascii码 static void CharToBit(const char input[], int output[]) { int i, j; for (j = 0; j < 8; j++) { for (i = 0; i < 8; i++) { output[7 * (j + 1) - i + j] = (input[j] >> i) & 1; // 先将input[j]转成二进制,然后向右移i位,取末尾的数字0或1 } } }; static void BitToChar(const int intput[], char output[]) //把INT转换为CHAR { int i, j; for (j = 0; j < 8; j++) { // 此for根据8位ASCII码转为对应的字符 for (i = 0; i < 8; i++) { // output初始元素都是'\0',对应的ASCII码为0 output[j] = output[j] * 2 + intput[i + 8 * j]; } } }; static void Xor(int *INA, int *INB, int len) //异或操作 { int i; for (i = 0; i < len; i++) { *(INA + i) = *(INA + i) ^ *(INB + i); // ^ 是异或 } }; //根据IP_Table进行初始IP置换 static void IP(const int input[64], int output[64], int table[64]) { int i; for (i = 0; i < 64; i++) { output[i] = input[table[i] - 1]; //减1操作不可少!! } }; // 选择运算E,参考table,把32位扩展为48位数据 static void E(const int input[32], int output[48], int table[48]) { int i; for (i = 0; i < 48; i++) { output[i] = input[table[i] - 1]; } }; static void P(const int input[32], int output[32], int table[32]) //P置换 { int i; for (i = 0; i < 32; i++) { output[i] = input[table[i] - 1]; } }; static void IP_In(const int input[64], int output[64], int table[64]) //逆IP { int i; for (i = 0; i < 64; i++) { output[i] = input[table[i] - 1]; } }; // 形参:input:初始的64位秘钥,table为参考矩阵 static void PC_1(const int input[64], int output[56], int table[56]) { int i; for (i = 0; i < 56; i++) { output[i] = input[table[i] - 1]; } }; // 置换选择2 // 形参:input:循环移位的结果,output:置换得到的最终的子秘钥 static void PC_2(const int input[56], int output[48], int table[48]) { int i; for (i = 0; i < 48; i++) { output[i] = input[table[i] - 1]; } }; // S盒压缩 // 让形参input经过代替函数组,存到output中 static void S(const int input[48], int output[32], int table[8][4][16]) { int i = 0; int j = 0; int INT[8]; // 循环8次 for (; i < 48; i = i + 6) { // 对应ppt26页的操作: // 先取input前6位,取S1盒,通过行列命中S1的一个元素,保存到INT[0]中; // 再取input第二个6位,取S2盒,通过行列命中S2的一个元素,保存到INT[1]中; // ... // 此时INT:[6个元通过S1的结果 6个元通过S2的结果 ... 6个元通过S8的结果],其中每个元素是十进制,但能转换为4位的二进制 INT[j] = table[j][(input[i] << 1) + (input[i + 5])][(input[i + 1] << 3) + (input[i + 2] << 2) + (input[i + 3] << 1) + (input[i + 4])]; j++; } // 将INT中的每个元素转为4位的二进制数,然后合并起来放到output中 for (j = 0; j < 8; j++) { for (i = 0; i < 4; i++) { output[3 * (j + 1) - i + j] = (INT[j] >> i) & 1; } } }; // 选择运算E // 参数:input:R,subkey:48位密钥 static void F_func(int input[32], int output[32], int subkey[48]) //完成DES算法轮变换 { int len = 48; int temp[48] = {0}; int temp_1[32] = {0}; // 选择运算将R扩展成48位,存到temp E(input, temp, E_Table); // 利用48密钥进行逐比特异或运算,结果存到temp中 Xor(temp, subkey, len); // 经过代替函数组,将32位的结果放到temp_1中 S(temp, temp_1, S_Box); // 经过置换运算P,结果保存到output里面 P(temp_1, output, P_Table); }; static void RotateL(const int input[28], int output[28], int leftCount) //秘钥循环左移 { int i; int len = 28; for (i = 0; i < len; i++) { output[i] = input[(i + leftCount) % len]; } }; //子密钥生成 //形参:input:64位初始秘钥,Subkey最终的16个子秘钥 static void subKey_fun(const int input[64], int Subkey[16][48]) { int loop = 1, loop_2 = 2; int i, j; int c[28], d[28]; int pc_1[56] = {0}; int pc_2[16][56] = {0}; int rotatel_c[16][28] = {0}; int rotatel_d[16][28] = {0}; // 在置换选择中进行置换,置换结果为一个长长的一维数组了:pc_1,里面包含了2个置换结果 PC_1(input, pc_1, PC1_Table); // 再把pc_1的2个置换结果拆分开,存到c[28],d[28] for (i = 0; i < 28; i++) { c[i] = pc_1[i]; d[i] = pc_1[i + 28]; } int leftCount = 0; // 下面的for实现: // rotatel_c: // 第1个子秘钥的c[28]循环移位的结果 // 第2个子秘钥的c[28]循环移位的结果 // ... // 第16个子秘钥的c[28]循环移位的结果 // rotatel_d: // 第1个子秘钥的d[28]循环移位的结果 // 第2个子秘钥的d[28]循环移位的结果 // ... // 第16个子秘钥的d[28]循环移位的结果 for (i = 1; i < 17; i++) { if (i == 1 || i == 2 || i == 9 || i == 16) { leftCount += loop; RotateL(c, rotatel_c[i - 1], leftCount); // 对c[28]循环左移leftCount,并把结果放到rotatel_c中 RotateL(d, rotatel_d[i - 1], leftCount); } else { leftCount += loop_2; RotateL(c, rotatel_c[i - 1], leftCount); RotateL(d, rotatel_d[i - 1], leftCount); } } // for实现 // pc_2 将矩阵rotatel_c和矩阵rotatel_d水平拼接,即: // 第1个子秘钥循环移位的结果 // ... // 第16个子秘钥循环移位的结果 for (i = 0; i < 16; i++) { for (j = 0; j < 28; j++) { pc_2[i][j] = rotatel_c[i][j]; pc_2[i][j + 28] = rotatel_d[i][j]; } } // 置换选择2 for (i = 0; i < 16; i++) { PC_2(pc_2[i], Subkey[i], PC2_Table); } }; // 整个加密算法 static void DES_Efun(char input[8], char key_in[8], int output[64]) { int Ip[64] = {0}; //存储初始置换后的矩阵 int output_1[64] = {0}; int subkeys[16][48]; int chartobit[64] = {0}; int key[64]; int l[17][32], r[17][32]; CharToBit(input, chartobit); //将字符形式的明文转换为64个二进制数的明文! IP(chartobit, Ip, IP_Table); //IP初始置换,结果保存到Ip[64]中 CharToBit(key_in, key); //初始化64位秘钥到key[64],这个初始秘钥是人为控制的 subKey_fun(key, subkeys); //生成16个48位的子秘钥到subkeys[16][48] // 将初始置换后的明文左右分开,l的第0行存明文左边,r的第0行存明文右边 for (int i = 0; i < 32; i++) { l[0][i] = Ip[i]; r[0][i] = Ip[32 + i]; } // 此for实现ppt第9页15次的蓝框操作 for (int j = 1; j < 16; j++) //前15轮的操作 { for (int k = 0; k < 32; k++) { l[j][k] = r[j - 1][k]; // 把ppt中的Ri-1赋值给Li } // 把r[j - 1]和subkeys[j - 1]传入f进行计算,结果保存到r[j] F_func(r[j - 1], r[j], subkeys[j - 1]); // 结果给r[j] Xor(r[j], l[j - 1], 32); } // 下面所有代码为最后一轮的操作 int t = 0; // R直接赋值给下面 for (t = 0; t < 32; t++) { r[16][t] = r[15][t]; } // 先经过f F_func(r[15], l[16], subkeys[15]); // 再经过异或,得到l[16] Xor(l[16], l[15], 32); // 此for把l[16]和r[16]拼成一个一维数组64位的output_1 for (t = 0; t < 32; t++) { output_1[t] = l[16][t]; output_1[32 + t] = r[16][t]; } // 经过最后的IP逆置换得到密文,存到output IP_In(output_1, output, IPR_Table); }; // 解密算法,与加密算法的唯一不同就是子密钥的使用顺序相反 static void DES_Dfun(int input[64], char key_in[8], char output[8]) { int Ip[64] = {0}; //存储初始置换后的矩阵 int output_1[64] = {0}; int output_2[64] = {0}; int subkeys[16][48]; int chartobit[64] = {0}; int key[64]; int l[17][32], r[17][32]; //IP初始置换,结果存入Ip[64]中 IP(input, Ip, IP_Table); // 转换为64位初始密钥 CharToBit(key_in, key); // 利用key生成16个子密钥到subkeys[16][48] subKey_fun(key, subkeys); // 分开生成l[0]和r[0] for (int i = 0; i < 32; i++) { l[0][i] = Ip[i]; r[0][i] = Ip[32 + i]; } // 此for实现ppt第9页15次的蓝框操作,不同的是密钥的顺序反了而已 for (int j = 1; j < 16; j++) //前15轮的操作 { for (int k = 0; k < 32; k++) { l[j][k] = r[j - 1][k]; } F_func(r[j - 1], r[j], subkeys[16 - j]); // 注意:密钥顺序反了 Xor(r[j], l[j - 1], 32); } int t = 0; // r直接赋值下来 for (t = 0; t < 32; t++) { r[16][t] = r[15][t]; } // 经过f和异或得到l[16],注意此时的密钥为K0 F_func(r[15], l[16], subkeys[0]); Xor(l[16], l[15], 32); // 左右合并 for (t = 0; t < 32; t++) { output_1[t] = l[16][t]; output_1[32 + t] = r[16][t]; } // 最后一个逆置换得到64位二进制明文了,存到output_2中 IP_In(output_1, output_2, IPR_Table); // 每8位二进制代表一个字符的ASCII码,将64位二进制明文转为8个字符 BitToChar(output_2, output); }; int main() { int output[64] = {0}; char MIN[9]; char MI[9]; // 随便输入8个字符做为明文存入MIN,一会儿会转为64位二进制明文,再输入系统(不要输入空格) cout << "input Message(8B)" << endl; cin >> MIN; // 随便输入8个字符做为密钥存入MI,一会儿会继续转为64位初始密钥,再输入系统(不要输入空格) cout << "input Key(8B)" << endl; cin >> MI; // 加密后,结果存output DES_Efun(MIN, MI, output); // 输出64位密文: cout << "Code:" << endl; for (int i = 0; i < 64; i++) { cout << output[i]; // 每次输出4位打一个换行符 //if ((i + 1) % 4 == 0) // printf("\n"); } cout << endl; // 以下解密: // 清空MIN,置为'0',此处的'0'的ASCII码为0,这是便于后面将ASCII码转为字符 for (int i = 0; i < 8; i++) MIN[i] = '0'; // 进行解密,output是刚才的密文,MI是刚才设置的密钥,解密结果后的明文存到MIN DES_Dfun(output, MI, MIN); cout << "After decryption:Message:" << endl; for (int i = 0; i < 8; i++) { cout << MIN[i]; } cout << endl; system("pause"); return 0; }
rc4:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> using namespace std; typedef unsigned long ULONG; // S表初始化 void rc4_init(int *s, unsigned char *key, unsigned long Len) { int i = 0, j = 0; // k[256]代表R表,只有第一个字符是ASCII为0的字符 char k[256] = {0}; unsigned char tmp = 0; // 对S表进行线性填充,利用密钥key对R表进行填充 // R表,即 k[256] : 密钥 密钥 密钥 .... 密钥,以字符形式保存,后期真正参与运算的是字符的ASCII码,字符只是代表的作用 for (i = 0; i < 256; i++) { s[i] = i; k[i] = key[i % Len]; } // 进行ppt46页第(4) for (i = 0; i < 256; i++) { j = (j + s[i] + k[i]) % 256; //交换s[i]和s[j] tmp = s[i]; s[i] = s[j]; s[j] = tmp; } } //加解密,第一个参数是S表,第二个是明文(或密文)的ASCII码表示,第三个是明文(或密文)的长度,最后结果保存到第二个参数,同时s表也发生了变化 void rc4_crypt(int *s, int *Data, unsigned long Len) { int i = 0, j = 0, t = 0; unsigned long k = 0; int tmp; int h; // 进行len次ppt第45页 for (k = 0; k < Len; k++) { i = (i + 1) % 256; j = (j + s[i]) % 256; //交换s[i]和s[j] tmp = s[i]; s[i] = s[j]; s[j] = tmp; t = (s[i] + s[j]) % 256; // 得到一个密钥字节 h = s[t]; // 1B明文和1B密钥字节异或得到加密结果 Data[k] = Data[k] ^ h; } } // 此时MIN_num:[第一个明文字符加密后的十进制数据 第二个明文字符加密后的十进制数据... 最后一个明文字符加密后的十进制数据] // MIN_num的每个元素的十进制的范围是0-255 // 此函数把每个十进制再转化为二进制,输出:第一个明文字符加密后的二进制数据 第二个明文字符加密后的二进制数据... 最后一个明文字符加密后的二进制数据] // 即打印最终的密文 void printCode(int *MIN_num, int len) { int temp[8]; for (int i = 0; i < len; i++) { for (int j = 0; j < 8; j++) { temp[7 - j] = (MIN_num[i] >> j) & 1; } for (int k = 0; k < 8; k++) { cout << temp[k]; } } cout << endl; } int main() { // unsigned char和char // 两者都作为字符用的话是没有区别的,但当整数用时有区别: // char 整数范围为-128到127 // unsigned char 整数范围为0到255 // s代表S表 int s[256] = {0}; int s2[256] = {0}; // 随便定义一个英文密钥MI,不限制长度,不再是8B了(不带空格) char MI[256]; cout << "请输入任意长度的英文密钥(不带空格):" << endl; cin >> MI; // 随便定义一个英文明文MIN,不限制长度,一个字母顶1B(不带空格) char MIN[512]; cout << "请输入任意长度的英文明文(不带空格):" << endl; cin >> MIN; // 为了用strlen计算长度,只能先定义为char型,最后做参数再强制转换为unsigned char cout << "此密钥长度:" << strlen(MI) << endl; cout << "此明文长度:" << strlen(MIN) << endl; // 把明文的每个字符转为ASCII码形式,存到NUM_NUM里面 int MIN_num[512]; for (int i = 0; i < 512; i++) { MIN_num[i] = MIN[i]; } //初始化S表,存到s中 rc4_init(s, (unsigned char *)MI, strlen(MI)); cout << "完成对S表的初始化,如下:" << endl; for (int i = 0; i < 256; i++) { cout << s[i] << " "; } cout << endl; //由于加密后s表会变化,此时先用s2保留好初始化的s表 for (int i = 0; i < 256; i++) { s2[i] = s[i]; } cout << "现在开始加密---------------------------------" << endl; rc4_crypt(s, MIN_num, strlen(MIN)); //加密时传入初始化的S表,最后将结果保存到MIN_num cout << "密文:" << endl; printCode(MIN_num, strlen(MIN)); cout << "解密上面密文---------------------------------" << endl; rc4_crypt(s2, MIN_num, strlen(MIN)); //解密时传入之前初始化的S表,最后将结果保存到MIN_num //将解密结果的ASCII码转换为字符形式 for (int i = 0; i < 512; i++) { MIN[i] = MIN_num[i]; } cout << "解密后的明文是:" << MIN << endl; system("pause"); return 0; }
rsa:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> using namespace std; // 扩展欧几里的算法,能够根据 ed =1 mod φ(n) ,求出d // 原理:计算 ax + by = 1中的x与y的整数解(a与b互质) void ext_gcd(int e, int fy, int *rxy) { if (fy == 0) { int x1 = 1; int y1 = 0; rxy[1] = x1; rxy[2] = y1; rxy[0] = e; } else { ext_gcd(fy, e % fy, rxy); int x = rxy[2]; int y = rxy[1] - e / fy * rxy[2]; rxy[1] = x; rxy[2] = y; } } // 十进制转倒序的二进制 // 返回二进制的长度 int bin(int dec, char *bin_array) { int i; for (i = 0; dec > 0; dec /= 2, i++) { bin_array[i] = dec % 2 + '0'; } return i; } // 原理:密码学\{5}--第5章公开密钥密码\{1}--公钥密码(1)\图a int multi(int *base_array, char *bin_array, int n, int base_array_len) { // 最终计算结果保存到result int result = 1; int a; // 遍历bin_array for (int index = 0; index < base_array_len; index++) { if (bin_array[index] == '0') // 假如扫描到二进制=0,相当于乘Ai的0次方,即1,即不用乘了,则跳过本次循环 { continue; } a = base_array[index]; result *= a; result = result % n; // 取模降低result的大小 } return result; } //实现:超大整数超大次幂然后对超大的整数取模 //即计算 (base ^ exponent) mod n //详细步骤见:密码学\{5}--第5章公开密钥密码\{1}--公钥密码(1)\图a int exp_mode(int base, int exponent, int n) { // 将exponent转为二进制,再倒叙过来 char bin_array[1000] = {'\0'}; int r = bin(exponent, bin_array); int base_array[100] = {0}; base_array[0] = base; // 此for循环 二进制的长度-1次,最后使得base_array:[A0 A1 A2 A3...Ar-1](mod n) for (int i = 0; i < r - 1; i++) { base_array[i + 1] = (base * base) % n; base = base_array[i + 1]; } int a_w_b = multi(base_array, bin_array, n, r); return a_w_b % n; } // 进行ppt第20页前1-5步 // 产生n和e存入pubkey // 产生d存入selfkey // 参数p、q是质数 void gen_key(int p, int q, int *pubkey, int *selfkey) { int n = p * q; // n = p * q。 int fy = (p - 1) * (q - 1); // 欧拉函数φ(n) = (p-1) * (q-1)保存到fy,意义是:[0,1,...,n-1]中n互质的整数个数 // int e = 65537; // 取e满足: 1 < e < φ(n) 且 (e, φ(n))=1,正式环境中取65537。 int e = 31; // 根据 ed =1 mod φ(n) ,求出d int rxy[3]; ext_gcd(e, fy, rxy); // 计算出的x的值就是d的值,但是d不能是负数,如果是负数,x=x+fy,使x为正数。 int d = rxy[1]; if (d < 0) { d = d + fy; } // 此时不再需要p,q,fy,将其销毁防止别人用来解密 // 把公开的n和e告诉任何人,他们都能加密 // 把私密的d和公开的n告诉解密者,只有解密者才能解出来 pubkey[0] = n; pubkey[1] = e; selfkey[0] = n; selfkey[1] = d; } // 加密 int encrypt(int MIN, int *pubkey) { int n = pubkey[0]; int e = pubkey[1]; // 计算密文 = 明文 ^ e mod n int re = exp_mode(MIN, e, n); // 如果模的结果是负数,则再加n if (re < 0) { re += n; } return re; } // 解密 参数c是密文,参数selfkey是解密钥匙 // 明文 = 密文 ^ d mod n int decrypt(int c, int *selfkey) { int n = selfkey[0]; int d = selfkey[1]; int MIN = exp_mode(c, d, n); if (MIN < 0) // 结果不能是负数 { MIN += n; } return MIN; } int main() { //定义两个大质数p,q // p = 106697219132480173106064317148705638676529121742557567770857687729397446898790451577487723991083173010242416863238099716044775658681981821407922722052778958942891831033512463262741053961681512908218003840408526915629689432111480588966800949428079015682624591636010678691927285321708935076221951173426894836169; // q = 144819424465842307806353672547344125290716753535239658417883828941232509622838692761917211806963011168822281666033695157426515864265527046213326145174398018859056439431422867957079149967592078894410082695714160599647180947207504108618794637872261572262805565517756922288320779308895819726074229154002310375209; int p = 67; int q = 73; int pubkey[2]; int selfkey[2]; //生成公钥 pubkey:[n,e],公钥e和n都可以被人知道 //此时私钥!=公钥,生成私钥d,存入到selfkey:[n,d],只能被解密人知道d //该过程不依赖于明文 gen_key(p, q, pubkey, selfkey); // RSA本质是在加密数字,现在把输入的明文转化为数字,再加密: // 假定有明文是一个字符,需要字符转化成十进制数字(利用ASCII) // 如果数字化后的明文字符<模n(此例为4891)且>=0,则没事 // 如果数字化后的明文字符>=模n,此时解密进行的模运算无法恢复到明文字符,此时需要:调大q和p使得n很大 // 输入明文,例如:MIN_CHAR:['H','i','!'] // MIN:[H对应的ASCII i对应的ASCII !对应的ASCII] char MIN_char[256] = {'\0'}; int MIN[256] = {0}; cout << "请输入任意长度的英文明文(不带空格):" << endl; cin >> MIN_char; for (int i = 0; i < strlen(MIN_char); i++) { MIN[i] = MIN_char[i]; } // 对MIN[i]进行加密,加密完后例如是72,则直接输出,接着解密,把解密结果放到re[i]中 int re[256] = {0}; cout << "密文:" << endl; for (int i = 0; i < strlen(MIN_char); i++) { //单个元素加密,c是对应密文 int c = encrypt(MIN[i], pubkey); cout << c << "-"; //解密后的明文为d int d = decrypt(c, selfkey); re[i] = d; } cout << endl; // 此时只得到每个字符解密后的数字,这个数字就是ASCII码,再转为字符 cout << "解密后明文:" << endl; for (int i = 0; i < strlen(MIN_char); i++) { cout << (char)re[i]; } cout << endl; system("pause"); return 0; }