下述为DES代码实现的完整过程,其中包括密钥扩展、DES实现、CBC模式(密码分组链接模式)和ECB模式(电码本模式),经过本人测试可直接运行使用,所有代码为本人原创,禁止转载
下述有分块介绍模块的详细介绍,但是如果各位不感兴趣可以直接拉到最下面,有完整代码
- DES的基本原理
其入口参数有三个:key、data、mode。Key为加密解密使用的密钥,data为加密解密的数据,mode为其工作模式。当模式为加密模式时,明文按照64位进行分组,形成明文组,key用于对数据加密,当模式为解密模式时,key用于对数据解密。实际运用中,密钥只用到了64位中的56位,这样才具有高的安全性。
初始化
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 };
// 逆初始置换
int IP_1[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 };
// 扩展置换表
int 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 };
// S盒
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}
}
};
// P置换
int 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 };
int PC1[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 s[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
// 密钥第二次置换表
int PC2[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
};
- 分组密码工作模式
密钥扩展
void generate_key(int origin_key[], int key[16][48]) //密钥扩展算法
{
int C[28], D[28];
for (int i = 0; i < 28; i++)
{
C[i] = origin_key[PC1[i]];
D[i] = origin_key[PC1[28+i]];
}
for (int i = 0; i < 16; i++)
{
int temp = s[i]; //左移次数
while (temp--)
{
//c,d为循环左移暂存区
int c = C[0];
int d = D[0];
for (int j = 1; j < 28; j++)
{
C[j - 1] = C[j];
D[j - 1] = D[j];
}
C[27] = c;
D[27] = d;
}
int result[56];
for (int j = 0; j < 28; j++)
{
result[j] = C[j];
result[28 + j] = D[j];
}
for (int j = 0; j < 48; j++)
key[i][j] = result[PC2[j]-1];
}
}
Feistel结构
void Feistel(int L[], int R[], int* key) //Feistel结构
{
int L_[32], R_[32];
int RF[33];
F(R, key,RF);
for (int i = 0; i < 32; i++)
{
L_[i] = R[i];
R_[i] = L[i] ^ RF[i];
}
for (int i = 0; i < 32; i++)
{
L[i] = L_[i];
R[i] = R_[i];
}
}
DES的工作模式:电码本模式(CB)、密码分组链接模式(CBC)。
char* DES(int key[16][48], int data[], char mode)
{
int L[32],R[32];
int temp[64];
static char proclaim[9];
memcpy(temp, data, sizeof(int) * 64);
if (mode == '1') //加密
{
for (int i = 0; i < 64; i++) //初始置换
data[i] = temp[IP[i] - 1];
for (int i = 0; i < 32; i++) //数据拆分成两部分
{
L[i] = data[i];
R[i] = data[32 + i];
}
for (int times = 0; times < 16; times++)
{
Feistel(L, R, key[times]);
cout << "第" << times << "轮加密结果:";
for (int i = 0; i < 32; i++)
cout << L[i];
for (int i = 0; i < 32; i++)
cout << R[i];
cout << endl;
}
int result[64];
for (int i = 0; i < 32; i++) //32bit互换
{
result[i] = R[i];
result[32 + i] = L[i];
}
for (int i = 0; i < 64; i++) //逆初始置换
data[i] = result[IP_1[i] - 1];
cout << "加密的二进制串为:";
for (int i = 0; i < 64; i++)
cout << data[i];
cout << endl;
int num = 8;
while (num--) //二进制数组转换为字符串
{
int t = 8;
int ch = 0;
while (t--)
{
ch = data[(7 - num) * 8 + (7 - t)] + ch * 2;
}
proclaim[(7 - num)] = ch;
}
proclaim[8] = '\0';
cout << "加密得到的密文为:" << proclaim << endl;
}
else //解密
{
for (int i = 0; i < 64; i++) //初始置换
data[i] = temp[IP[i] - 1];
for (int i = 0; i < 32; i++) //数据拆分成两部分
{
L[i] = data[i];
R[i] = data[32 + i];
}
for (int times = 15; times >= 0; times--)
Feistel(L, R, key[times]);
int result[64];
for (int i = 0; i < 32; i++) //32bit互换
{
result[i] = R[i];
result[32 + i] = L[i];
}
for (int i = 0; i < 64; i++) //逆初始置换
data[i] = result[IP_1[i] - 1];
cout << "解密的二进制串为:";
for (int i = 0; i < 64; i++)
cout << data[i];
cout << endl;
int num = 8;
while (num--) //二进制数组转换为字符串
{
int t = 8;
int ch = 0;
while (t--)
{
ch = data[(7 - num) * 8 + (7 - t)] + ch * 2;
}
proclaim[(7 - num)] = ch;
}
proclaim[8] = '\0';
}
return proclaim;
}
F函数
void F(int R[], int* key,int Rf[]) //F函数
{
int RR[48];
for (int i = 0; i < 48; i++) //E置换并与密钥异或
{
RR[47 - i] = R[32 - E[i]];
RR[47 - i] = RR[47 - i] ^ key[47 - i];
}
int x = 0;
for (int i = 0; i < 8; i++) //S_i置换
{
int row = RR[47 - i] * 2 + RR[47 - i - 5];
int column = RR[47 - i - 1] * 8 + RR[47 - i - 2] * 4 + RR[47 - i - 3] * 2 + RR[47 - i - 4];
int result = S[i / 6][row][column];
bitset<4> bit(result);
for (int j = 0; j < 4; j++)
Rf[31 - x - j] = bit[3 - j];
x = x + 4;
}
int temp[32];
memcpy(temp, Rf, sizeof(int) * 32);
for (int i = 0; i < 32; i++)
Rf[32 - i] = temp[32 - P[i]];
}
字符串转换二进制串
void Bit_char(char* data,int bit_data[]) //字符串转换为二进制bit
{
int temp = 0;
int i;
for (i = 0; i < 8; i++)
{
if (data[i] != '\0')
{
bitset<8> bit = bitset<8>(data[i]);
for (int j = 7; j >= 0; j--)
bit_data[temp++] = bit[j];
}
else
break;
}
while (temp < 64)
{
bit_data[temp++] = 0;
}
}
ECB模式的加密过程:
void ECB(int key[16][48], int data[64][64],char modle) //电码本模式
{
char* str;
if (modle == '1')
{
str = DES(key, data[0], '1');
ofstream ECB_1("ECB_1.txt");
ECB_1 << str;
ECB_1.close();
ofstream ECB_11("ECB_11.txt", ios::binary | ios::out);
ECB_11.write((char*)&data[0], sizeof(data[0]));
ECB_11.close();
for (int i = 1; i < 64; i++) //加密
{
str=DES(key, data[i], '1');
ofstream ECB_1("ECB_1.txt", std::ios_base::app);
ECB_1 << str;
ECB_1.close();
ofstream ECB_11("ECB_11.txt", ios::binary | ios::out | ios::app);
ECB_11.write((char*)&data[i], sizeof(data[i]));
ECB_11.close();
}
cout << "加密结果已存入ECB_1.txt中,二进制结果存入ECB11.txt中" << endl;
}
else
{
str = DES(key, data[0], '2');
ofstream ECB_2("ECB_2.txt");
ECB_2 << str;
ECB_2.close();
for (int i = 1; i < 64; i++) //解密
{
str=DES(key, data[i], '2');
ofstream ECB_2("ECB_2.txt", std::ios_base::app);
ECB_2 << str;
ECB_2.close();
}
cout << "解密结果已存入ECB_2.txt文件中" << endl;
}
}
CBC模式的加密过程:
void CBC(int key[16][48], int data[64][64], char modle) //密码分组链接模式
{
char IV[9] = "E0191410";
int IV_bit[64];
Bit_char(IV, IV_bit);
int chip[64][64];
for (int i = 0; i < 64; i++)
for (int j = 0; j < 64; j++)
chip[i][j] = data[i][j];
if (modle == '1')
{
char* str;
for (int i = 0; i < 64; i++)
data[0][i] = data[0][i] ^ IV_bit[i];
str=DES(key, data[0], modle);
ofstream CBC_11("CBC_11.txt", ios::binary | ios::out);
CBC_11.write((char*)&data[0], sizeof(data[0]));
CBC_11.close();
ofstream CBC_1("CBC_1.txt");
CBC_1 << str;
CBC_1.close();
for (int i = 1; i < 64; i++)
{
for (int j = 0; j < 64; j++)
data[i][j] = data[i][j] ^ data[i - 1][j];
DES(key, data[i], modle);
ofstream CBC_11("CBC_11.txt", ios::binary | ios::out | ios::app);
CBC_11.write((char*)&data[i], sizeof(data[i]));
CBC_11.close();
ofstream CBC_1("CBC_1.txt", std::ios_base::app);
CBC_1 << str;
CBC_1.close();
}
cout << "加密结果已存入CBC_1.txt中,加密的二进制结果已存入CBC_11.txt中" << endl;
}
else
{
char str[513];
str[512] = '\0';
int tt = 0;
DES(key, data[0], modle);
for (int i = 0; i < 64; i++)
data[0][i] = data[0][i] ^ IV_bit[i];
//二进制转换为字符串
int num = 8;
while (num--) //二进制数组转换为字符串
{
int t = 8;
int ch = 0;
while (t--)
{
ch = data[0][(7 - num) * 8 + (7 - t)] + ch * 2;
}
str[tt++] = ch;
}
for (int i = 1; i < 64; i++)
{
DES(key, data[i], '2');
for (int j = 0; j < 64; j++)
data[i][j] = data[i][j] ^ chip[i - 1][j];
//二进制转换为字符串
int num = 8;
while (num--) //二进制数组转换为字符串
{
int t = 8;
int ch = 0;
while (t--)
{
ch = data[i][(7 - num) * 8 + (7 - t)] + ch * 2;
}
str[tt++] = ch;
}
}
ofstream CBC_2("CBC_2.txt");
CBC_2 << str;
CBC_2.close();
}
}
测试代码(主函数main代码)
void main()
{
char data[9];
char key[9];
char mode;
int bit_data[64];
char choose;
cout << "1、DES加密、解密\n2、分组密码模式\n请选择:";
cin >> choose;
if (choose != '1' && choose != '2')
{
cout << "输入有误,退出程序";
exit(0);
}
else if (choose == '1')
{
cout << "1、加密\n2、解密\n您选择:";
cin >> mode;
if (mode != '1' && mode != '2')
{
cout << "输入有误,退出程序";
exit(0);
}
else if (mode == '1')
{
cout << "请输入需要加密的8字节明文:";
cin >> data;
Bit_char(data, bit_data);
}
else
{
fstream file;
file.open("result_1.txt", ios::binary | ios::in);
file.read((char*)&data, sizeof(data));
file.close();
Bit_char(data, bit_data);
cout << "已从result_1.txt文件中加载获取密文" << endl;
}
cout << "请输入加密所需的8字节密钥:";
cin >> key;
int bit_key[64];
char *str;
Bit_char(key, bit_key);
int k[16][48];
generate_key(bit_key, k);
str=DES(k, bit_data, mode);
if (mode == '1')
{
//加密结果存入文件中
ofstream file("result_1.txt");
file << str;
file.close();
cout << "加密结果已存入result_1.txt文件中" << endl;
}
if (mode == '2')
{
//加密结果存入文件中
ofstream file("result_2.txt");
file << str;
file.close();
cout << "解密结果已存入result_2.txt文件中" << endl;
}
}
else
{
cout << "1、电码本模式\n2、密码分组链接模式\n请选择:";
cin >> mode;
cout << "请输入加密所需的8字节密钥:";
cin >> key;
int bit_key[64];
Bit_char(key, bit_key);
static int k[16][48];
generate_key(bit_key, k);
char modle;
cout << "1、加密\n2、解密\n请选择:";
cin >> modle;
int data_bit[64][64];
if (modle == '1')
{
fstream file;
char source[512];
file.open("source.txt", ios::in);
file.read((char*)&source, sizeof(source));
file.close();
for (int i = 0; i < 64; i++) //字符转换为二进制串
{
for (int j = 0; j < 8; j++)
data[j] = source[i * 8 + j];
Bit_char(data, data_bit[i]);
}
}
if (mode != '1' && mode != '2')
{
cout << "输入有误,退出程序";
exit(0);
}
if (mode == '1')
{
int data_all[4096];
if(modle=='2')
{
fstream ECB;
ECB.open("ECB_11.txt", ios::binary | ios::in);
ECB.read((char*)&data_all, sizeof(data_all));
ECB.close();
cout << "已从ECB_11.txt文件中加载获取密文" << endl;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < 64; j++)
{
data_bit[i][j] = data_all[i * 64 + j];
}
}
}
ECB(k, data_bit, modle);
}
else
{
int data_all[4096];
if (modle == '2')
{
fstream CBC;
CBC.open("CBC_11.txt", ios::binary | ios::in);
CBC.read((char*)&data_all, sizeof(data_all));
CBC.close();
cout << "已从CBC_11.txt文件中加载获取密文" << endl;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < 64; j++)
{
data_bit[i][j] = data_all[i * 64 + j];
}
}
}
CBC(k, data_bit, modle);
}
}
}
完整代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <fstream>
#include<bitset>
#include<string>
using namespace std;
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 };
// 逆初始置换
int IP_1[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 };
// 扩展置换表
int 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 };
// S盒
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}
}
};
// P置换
int 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 };
int PC1[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 s[16] = { 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 };
// 密钥第二次置换表
int PC2[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
};
void Bit_char(char* data,int bit_data[]) //字符串转换为二进制bit
{
int temp = 0;
int i;
for (i = 0; i < 8; i++)
{
if (data[i] != '\0')
{
bitset<8> bit = bitset<8>(data[i]);
for (int j = 7; j >= 0; j--)
bit_data[temp++] = bit[j];
}
else
break;
}
while (temp < 64)
{
bit_data[temp++] = 0;
}
}
void F(int R[], int* key,int Rf[]) //F函数
{
int RR[48];
for (int i = 0; i < 48; i++) //E置换并与密钥异或
{
RR[47 - i] = R[32 - E[i]];
RR[47 - i] = RR[47 - i] ^ key[47 - i];
}
int x = 0;
for (int i = 0; i < 8; i++) //S_i置换
{
int row = RR[47 - i] * 2 + RR[47 - i - 5];
int column = RR[47 - i - 1] * 8 + RR[47 - i - 2] * 4 + RR[47 - i - 3] * 2 + RR[47 - i - 4];
int result = S[i / 6][row][column];
bitset<4> bit(result);
for (int j = 0; j < 4; j++)
Rf[31 - x - j] = bit[3 - j];
x = x + 4;
}
int temp[32];
memcpy(temp, Rf, sizeof(int) * 32);
for (int i = 0; i < 32; i++)
Rf[32 - i] = temp[32 - P[i]];
}
void Feistel(int L[], int R[], int* key) //Feistel结构
{
int L_[32], R_[32];
int RF[33];
F(R, key,RF);
for (int i = 0; i < 32; i++)
{
L_[i] = R[i];
R_[i] = L[i] ^ RF[i];
}
for (int i = 0; i < 32; i++)
{
L[i] = L_[i];
R[i] = R_[i];
}
}
void generate_key(int origin_key[], int key[16][48]) //密钥扩展算法
{
int C[28], D[28];
for (int i = 0; i < 28; i++)
{
C[i] = origin_key[PC1[i]];
D[i] = origin_key[PC1[28+i]];
}
for (int i = 0; i < 16; i++)
{
int temp = s[i]; //左移次数
while (temp--)
{
//c,d为循环左移暂存区
int c = C[0];
int d = D[0];
for (int j = 1; j < 28; j++)
{
C[j - 1] = C[j];
D[j - 1] = D[j];
}
C[27] = c;
D[27] = d;
}
int result[56];
for (int j = 0; j < 28; j++)
{
result[j] = C[j];
result[28 + j] = D[j];
}
for (int j = 0; j < 48; j++)
key[i][j] = result[PC2[j]-1];
}
}
char* DES(int key[16][48], int data[], char mode)
{
int L[32],R[32];
int temp[64];
static char proclaim[9];
memcpy(temp, data, sizeof(int) * 64);
if (mode == '1') //加密
{
for (int i = 0; i < 64; i++) //初始置换
data[i] = temp[IP[i] - 1];
for (int i = 0; i < 32; i++) //数据拆分成两部分
{
L[i] = data[i];
R[i] = data[32 + i];
}
for (int times = 0; times < 16; times++)
{
Feistel(L, R, key[times]);
cout << "第" << times << "轮加密结果:";
for (int i = 0; i < 32; i++)
cout << L[i];
for (int i = 0; i < 32; i++)
cout << R[i];
cout << endl;
}
int result[64];
for (int i = 0; i < 32; i++) //32bit互换
{
result[i] = R[i];
result[32 + i] = L[i];
}
for (int i = 0; i < 64; i++) //逆初始置换
data[i] = result[IP_1[i] - 1];
cout << "加密的二进制串为:";
for (int i = 0; i < 64; i++)
cout << data[i];
cout << endl;
int num = 8;
while (num--) //二进制数组转换为字符串
{
int t = 8;
int ch = 0;
while (t--)
{
ch = data[(7 - num) * 8 + (7 - t)] + ch * 2;
}
proclaim[(7 - num)] = ch;
}
proclaim[8] = '\0';
cout << "加密得到的密文为:" << proclaim << endl;
}
else //解密
{
for (int i = 0; i < 64; i++) //初始置换
data[i] = temp[IP[i] - 1];
for (int i = 0; i < 32; i++) //数据拆分成两部分
{
L[i] = data[i];
R[i] = data[32 + i];
}
for (int times = 15; times >= 0; times--)
Feistel(L, R, key[times]);
int result[64];
for (int i = 0; i < 32; i++) //32bit互换
{
result[i] = R[i];
result[32 + i] = L[i];
}
for (int i = 0; i < 64; i++) //逆初始置换
data[i] = result[IP_1[i] - 1];
cout << "解密的二进制串为:";
for (int i = 0; i < 64; i++)
cout << data[i];
cout << endl;
int num = 8;
while (num--) //二进制数组转换为字符串
{
int t = 8;
int ch = 0;
while (t--)
{
ch = data[(7 - num) * 8 + (7 - t)] + ch * 2;
}
proclaim[(7 - num)] = ch;
}
proclaim[8] = '\0';
}
return proclaim;
}
void ECB(int key[16][48], int data[64][64],char modle) //电码本模式
{
char* str;
if (modle == '1')
{
str = DES(key, data[0], '1');
ofstream ECB_1("ECB_1.txt");
ECB_1 << str;
ECB_1.close();
ofstream ECB_11("ECB_11.txt", ios::binary | ios::out);
ECB_11.write((char*)&data[0], sizeof(data[0]));
ECB_11.close();
for (int i = 1; i < 64; i++) //加密
{
str=DES(key, data[i], '1');
ofstream ECB_1("ECB_1.txt", std::ios_base::app);
ECB_1 << str;
ECB_1.close();
ofstream ECB_11("ECB_11.txt", ios::binary | ios::out | ios::app);
ECB_11.write((char*)&data[i], sizeof(data[i]));
ECB_11.close();
}
cout << "加密结果已存入ECB_1.txt中,二进制结果存入ECB11.txt中" << endl;
}
else
{
str = DES(key, data[0], '2');
ofstream ECB_2("ECB_2.txt");
ECB_2 << str;
ECB_2.close();
for (int i = 1; i < 64; i++) //解密
{
str=DES(key, data[i], '2');
ofstream ECB_2("ECB_2.txt", std::ios_base::app);
ECB_2 << str;
ECB_2.close();
}
cout << "解密结果已存入ECB_2.txt文件中" << endl;
}
}
void CBC(int key[16][48], int data[64][64], char modle) //密码分组链接模式
{
char IV[9] = "E0191410";
int IV_bit[64];
Bit_char(IV, IV_bit);
int chip[64][64];
for (int i = 0; i < 64; i++)
for (int j = 0; j < 64; j++)
chip[i][j] = data[i][j];
if (modle == '1')
{
char* str;
for (int i = 0; i < 64; i++)
data[0][i] = data[0][i] ^ IV_bit[i];
str=DES(key, data[0], modle);
ofstream CBC_11("CBC_11.txt", ios::binary | ios::out);
CBC_11.write((char*)&data[0], sizeof(data[0]));
CBC_11.close();
ofstream CBC_1("CBC_1.txt");
CBC_1 << str;
CBC_1.close();
for (int i = 1; i < 64; i++)
{
for (int j = 0; j < 64; j++)
data[i][j] = data[i][j] ^ data[i - 1][j];
DES(key, data[i], modle);
ofstream CBC_11("CBC_11.txt", ios::binary | ios::out | ios::app);
CBC_11.write((char*)&data[i], sizeof(data[i]));
CBC_11.close();
ofstream CBC_1("CBC_1.txt", std::ios_base::app);
CBC_1 << str;
CBC_1.close();
}
cout << "加密结果已存入CBC_1.txt中,加密的二进制结果已存入CBC_11.txt中" << endl;
}
else
{
char str[513];
str[512] = '\0';
int tt = 0;
DES(key, data[0], modle);
for (int i = 0; i < 64; i++)
data[0][i] = data[0][i] ^ IV_bit[i];
//二进制转换为字符串
int num = 8;
while (num--) //二进制数组转换为字符串
{
int t = 8;
int ch = 0;
while (t--)
{
ch = data[0][(7 - num) * 8 + (7 - t)] + ch * 2;
}
str[tt++] = ch;
}
for (int i = 1; i < 64; i++)
{
DES(key, data[i], '2');
for (int j = 0; j < 64; j++)
data[i][j] = data[i][j] ^ chip[i - 1][j];
//二进制转换为字符串
int num = 8;
while (num--) //二进制数组转换为字符串
{
int t = 8;
int ch = 0;
while (t--)
{
ch = data[i][(7 - num) * 8 + (7 - t)] + ch * 2;
}
str[tt++] = ch;
}
}
ofstream CBC_2("CBC_2.txt");
CBC_2 << str;
CBC_2.close();
}
}
void main()
{
char data[9];
char key[9];
char mode;
int bit_data[64];
char choose;
cout << "1、DES加密、解密\n2、分组密码模式\n请选择:";
cin >> choose;
if (choose != '1' && choose != '2')
{
cout << "输入有误,退出程序";
exit(0);
}
else if (choose == '1')
{
cout << "1、加密\n2、解密\n您选择:";
cin >> mode;
if (mode != '1' && mode != '2')
{
cout << "输入有误,退出程序";
exit(0);
}
else if (mode == '1')
{
cout << "请输入需要加密的8字节明文:";
cin >> data;
Bit_char(data, bit_data);
}
else
{
fstream file;
file.open("result_1.txt", ios::binary | ios::in);
file.read((char*)&data, sizeof(data));
file.close();
Bit_char(data, bit_data);
cout << "已从result_1.txt文件中加载获取密文" << endl;
}
cout << "请输入加密所需的8字节密钥:";
cin >> key;
int bit_key[64];
char *str;
Bit_char(key, bit_key);
int k[16][48];
generate_key(bit_key, k);
str=DES(k, bit_data, mode);
if (mode == '1')
{
//加密结果存入文件中
ofstream file("result_1.txt");
file << str;
file.close();
cout << "加密结果已存入result_1.txt文件中" << endl;
}
if (mode == '2')
{
//加密结果存入文件中
ofstream file("result_2.txt");
file << str;
file.close();
cout << "解密结果已存入result_2.txt文件中" << endl;
}
}
else
{
cout << "1、电码本模式\n2、密码分组链接模式\n请选择:";
cin >> mode;
cout << "请输入加密所需的8字节密钥:";
cin >> key;
int bit_key[64];
Bit_char(key, bit_key);
static int k[16][48];
generate_key(bit_key, k);
char modle;
cout << "1、加密\n2、解密\n请选择:";
cin >> modle;
int data_bit[64][64];
if (modle == '1')
{
fstream file;
char source[512];
file.open("source.txt", ios::in);
file.read((char*)&source, sizeof(source));
file.close();
for (int i = 0; i < 64; i++) //字符转换为二进制串
{
for (int j = 0; j < 8; j++)
data[j] = source[i * 8 + j];
Bit_char(data, data_bit[i]);
}
}
if (mode != '1' && mode != '2')
{
cout << "输入有误,退出程序";
exit(0);
}
if (mode == '1')
{
int data_all[4096];
if(modle=='2')
{
fstream ECB;
ECB.open("ECB_11.txt", ios::binary | ios::in);
ECB.read((char*)&data_all, sizeof(data_all));
ECB.close();
cout << "已从ECB_11.txt文件中加载获取密文" << endl;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < 64; j++)
{
data_bit[i][j] = data_all[i * 64 + j];
}
}
}
ECB(k, data_bit, modle);
}
else
{
int data_all[4096];
if (modle == '2')
{
fstream CBC;
CBC.open("CBC_11.txt", ios::binary | ios::in);
CBC.read((char*)&data_all, sizeof(data_all));
CBC.close();
cout << "已从CBC_11.txt文件中加载获取密文" << endl;
for (int i = 0; i < 64; i++)
{
for (int j = 0; j < 64; j++)
{
data_bit[i][j] = data_all[i * 64 + j];
}
}
}
CBC(k, data_bit, modle);
}
}
}
附加问题:DES与AES的不同之处
AES特征
AES是分组密码
数据是128比特,密钥是128/192/256比特
比3DES安全性高、速度快
提供完整的规范和设计细节
能在多种平台上以较快的速度实现
DES的特征
分组加密算法:明文和密文为64位分组长度;
对称算法:加密和解密除密钥编排不同外,使用同一算法;
密钥长度:64位,但每个字节第8位为奇偶校验位,可忽略;
密钥可为任意的56位数,但存在弱密钥,尽量避开;
采用混乱和扩散的组合,每个组合先替代后置换,共16轮;
只使用了标准的算术和逻辑运算,易于实现。
详细资源: