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; }
来源:https://www.cnblogs.com/pjishu/p/12416984.html