密码学DES的C++实现(完整)

下述为DES代码实现的完整过程,其中包括密钥扩展、DES实现、CBC模式(密码分组链接模式)和ECB模式(电码本模式),经过本人测试可直接运行使用,所有代码为本人原创,禁止转载

下述有分块介绍模块的详细介绍,但是如果各位不感兴趣可以直接拉到最下面,有完整代码

  1. 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
};
  1. 分组密码工作模式

密钥扩展

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轮;

只使用了标准的算术和逻辑运算,易于实现。 

详细资源:

实现DES的工作模式(包括DES和CBC、ECB)-网络安全文档类资源-CSDN文库

  • 14
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是Feistel加密算法C++代码实现: ```c++ #include <iostream> #include <cstring> #include <bitset> #include <algorithm> using namespace std; const int N = 10010; // 将字符串转换为二进制位串 bitset<N> str2bin(string s) { bitset<N> res; int len = s.length(); for (int i = 0; i < len; i++) { bitset<8> b(s[i]); // 将字符转换为8位二进制串 for (int j = 0; j < 8; j++) { res[i * 8 + j] = b[7 - j]; } } return res; } // 将二进制位串转换为字符串 string bin2str(bitset<N> b) { string res; int len = b.count() / 8; for (int i = 0; i < len; i++) { bitset<8> tmp; for (int j = 0; j < 8; j++) { tmp[7 - j] = b[i * 8 + j]; } res += char(tmp.to_ulong()); // 将8位二进制串转换为字符 } return res; } // Feistel加密算法 bitset<N> Feistel(bitset<N> plaintext, bitset<N> key, int rounds) { int half_size = plaintext.size() / 2; // 将明文分为左右两部分 bitset<N> left = plaintext >> half_size; bitset<N> right = plaintext & ((1 << half_size) - 1); // 迭代加密 for (int i = 0; i < rounds; i++) { bitset<N> tmp = left; left = right; right = tmp ^ (right ^ key); } // 将左右两部分合并 bitset<N> ciphertext = (left << half_size) | right; return ciphertext; } int main() { string plaintext, key; int rounds; cout << "请输入明文:"; getline(cin, plaintext); cout << "请输入密钥:"; cin >> key; cout << "请输入加密轮数:"; cin >> rounds; // 将明文和密钥转换为二进制位串 bitset<N> plaintext_bin = str2bin(plaintext); bitset<N> key_bin = str2bin(key); // 对明文进行加密 bitset<N> ciphertext_bin = Feistel(plaintext_bin, key_bin, rounds); // 将密文转换为字符串 string ciphertext = bin2str(ciphertext_bin); cout << "加密结果:" << ciphertext << endl; return 0; } ``` 其中,`str2bin()`函数将字符串转换为二进制位串,`bin2str()`函数将二进制位串转换为字符串,`Feistel()`函数实现了Feistel加密算法。在`main()`函数中,用户输入明文、密钥和加密轮数,程序对明文进行加密,并输出密文。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ACanary

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值