DES的代码C++实现

该代码实现了一个基于DES(DataEncryptionStandard)算法的加密和解密过程,包括IP置换、子密钥生成、F函数、S盒等核心步骤。加密时,明文经过填充、分组、加密;解密时,密文经过解密得到原文。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DES C++分组实现

  • 主CPP代码
#include<iostream>
#include<string>
#include"Numbertables.h"
#define N 50
using namespace std;
typedef bool BITE;
class DES_ALG {
public:
	//des加密或者解密算法函数入口
	void DesEnter(string &Data_in, BITE** Data_Out,string key, int Mode, int dataLen);
	//数据校验函数,暂未使用
	int DesMac(const BITE* mac_data, BITE*mac_code,int datalen, BITE key[64]);
	//取数据个数
	int Get_Nums();
	//取组数
	int Get_GroupNUm();

private:

	//数据个数
	int NumS = 0;
	int GroupNum = 0;
	//异或
	void XOR(BITE* Data_Out, BITE* Data_In, int Num);
	//创造子秘钥
	void CreSubKey(string Data_in);
	//加密
	void Enc_DES(BITE* Mes_Out, string Mes_In);
	//解密
	void Dec_DES(string &Mes_Out, BITE* Mes_In);
	//ASCII转换成bit
	void ASC_Bin(BITE* Data_Out, string Data_in, int Num);
	//bit转换成ASCII对应的字符
	void Bin_ASC(string &Mes_out, BITE* Mes_In, int Num);
	//置换
	void TableTrans(BITE* Date_Out, BITE* Data_In, const char* table, int Num);
	//数组复制
	void BitsCopy(BITE* Data_Out, BITE* Data_In, int Num);
	//移位
	void LoopMove(BITE* Data_In, int Len, int Num);
	//F函数
	void F_change(BITE Data_In[32], BITE Data_Ki[48]);
	//S盒
	void S_change(BITE Data_Out[32], BITE Data_In[48]);
};


int DES_ALG::Get_Nums() {
	return NumS;
}
int DES_ALG::Get_GroupNUm() {
	return GroupNum;
}
void PrintBin(BITE* data, int Num) {
	int i = 0;
	for (; i < Num; i++) {
		cout << data[i];
		if ((i+1) % 8 == 0) { cout << endl; }
	}
	cout << endl;
}
//二进制转string Mes_out转换后的字符串,Mes_In输入的2进制数组,Num是二进制的个数
void DES_ALG::Bin_ASC(string &Mes_out, BITE* Mes_In, int Num) {
	int i = 0;
	for (; i < Num; i += 8) {
		int temp = (Mes_In[i+7] << 7) + (Mes_In[i + 6] << 6) + (Mes_In[i + 5] << 5) + (Mes_In[i + 4] << 4) + (Mes_In[i + 3] << 3) + (Mes_In[i + 2] << 2) + (Mes_In[i + 1] << 1) + Mes_In[i];
		char te = char(temp);
		Mes_out.push_back(te);
	}
}
//ascii转bit
void DES_ALG::ASC_Bin(BITE * Data_Out,string Data_in,int Num) {
	int i = 0;
	for (; i < Num; i++) {
		Data_Out[i] = (Data_in[i/8] >> (i % 8)) & 1;
	}
}
//复制
void DES_ALG::BitsCopy(BITE *Data_Out,BITE *Data_In,int Num) {
	int i = 0;
	for (; i < Num; i++) {
		Data_Out[i] = Data_In[i];
	}
}
//选择置换函数
void DES_ALG::TableTrans(BITE * Date_Out,BITE *Data_In,const char *table,int Num) {
	int i = 0;
	static BITE temp[256] = { 0 };
	for (; i < Num; i++) {
		temp[i] = Data_In[table[i] - 1];
	}
	BitsCopy(Date_Out, temp, Num);

}
//循环移位 Len表示数据的长度,Num表示需要移位数
void DES_ALG::LoopMove(BITE * Data_In,int Len,int Num) {
	static BITE Temp[256] = { 0 };
	BitsCopy(Temp, Data_In, Num);
	BitsCopy(Data_In, Data_In + Num, Len - Num);
	BitsCopy(Data_In + Len - Num, Temp, Num);

}
//创建子秘钥函数  Data_in是8字节秘钥
void DES_ALG::CreSubKey(string Data_in) {
	int i = 0;
	static BITE KeyBit[64] = { 0 };
	//子秘钥在第一轮PC1置换选择后,通过选择只取了56位
	static bool* KiL = &KeyBit[0], * KiR = &KeyBit[28];
	ASC_Bin(KeyBit, Data_in, 64);
	//PCI选择置换(64bit-->56bit)
	TableTrans(KeyBit, KeyBit, PC1_Table, 56);
	//16论子秘钥的生产
	for (i = 0; i < 16; i++) {
		LoopMove(KiL, 28, Move_Table[i]);
		LoopMove(KiR, 28, Move_Table[i]);
		//PCII选择置换
		TableTrans(SubKey[i], KeyBit, PC2_Table,48);
	}
}
//对明文的操作F函数--1、E扩展 2.与秘钥异或 3.S盒压缩  4.P置换  5.L异或
//异或
void DES_ALG::XOR(BITE * Data_Out,BITE * Data_In,int Num) {
	int i = 0;
	for (; i < Num; i++) {
		Data_Out[i] = Data_Out[i] ^ Data_In[i];
	}
}
//S盒压缩
void DES_ALG::S_change(BITE Data_Out[32],BITE Data_In[48]) {
//i表示当前处理的数据的行数,也是选择的S盒的位置,X表示该S盒的行,Y表示该S盒的列
	int i, X, Y;
	for (i = 0, X = 0, Y = 0; i < 8; Data_In += 6, i++) {
		X = (Data_In[0] << 1) + Data_In[5];
		Y = (Data_In[1] << 3) + (Data_In[2] << 2) + (Data_In[3] << 1) + Data_In[4];
		ASC_Bin(Data_Out + i * 4, &S_Box[i][X][Y], 4);
	}
}
void DES_ALG::F_change(BITE Data_In[32],BITE Data_Ki[48]) {
	static bool MiR[48] = { 0 };
	//E扩展
	TableTrans(MiR, Data_In, E_Table, 48);
	//与秘钥异或
	XOR(MiR, Data_Ki, 48);
	//S盒压缩
	S_change(Data_In, MiR);
	//P置换
	TableTrans(Data_In, Data_In, P_Table, 32);
}
//加密 输入是string串,输出是密文二进制数组 Mes_In是秘钥,Mes_out是加密后的二进制密文
void DES_ALG::Enc_DES(BITE *Mes_Out,string Mes_In) {
	int i = 0;
	//在F函数之前存下R
	 BITE temp[32] = { 0 };
	//对半分
	 BITE* MiL = &Mes_Out[0], * MiR = &Mes_Out[32];
	ASC_Bin(Mes_Out, Mes_In, 64);
	cout << "明文二进制串:"<<endl;
	PrintBin(Mes_Out, 64);
	//IP置换
	TableTrans(Mes_Out, Mes_Out, IP_Table, 64);
	//16轮迭代
	for (; i < 16; i++) {
		BitsCopy(temp, MiR, 32);
		F_change(MiR, SubKey[i]);
		XOR(MiR, MiL, 32);
		BitsCopy(MiL, temp, 32);
	}
	//IP逆置换
	TableTrans(Mes_Out, Mes_Out, IPR_Table, 64);

}
//解密输入和输出都是sting Mes_In输入二进制密文,Mes_Out是输出密文
void DES_ALG::Dec_DES(string &Mes_Out,BITE *Mes_In) {
	int i = 15;
	 BITE temp[32] = { 0 };
	//对半分
	BITE MES_OUT[64] = { 0 };
	 BITE* MiL = &MES_OUT[0], * MiR = &MES_OUT[32];
	//IP置换
	TableTrans(MES_OUT, Mes_In, IP_Table, 64);
	//16轮迭代
	for (; i >=0; i--) {
		BitsCopy(temp, MiL, 32);
		F_change(MiL, SubKey[i]);
		XOR(MiL, MiR, 32);
		BitsCopy(MiR, temp, 32);
	}
	//IP逆置换
	TableTrans(MES_OUT, MES_OUT, IPR_Table, 64);
	cout << "解密后的二进制串:" << endl;
	PrintBin(MES_OUT, 64);
	Bin_ASC(Mes_Out, MES_OUT, 64); 

}
//DES主过程函数  加密模式:Data_in是明文,Data_out是二进制密文,解密模式,Data_in是解密结果明文,Data_out是密文,dataLen后期长度超过64位时使用,key秘钥,Mode是选择加密或者解密--1加密,0解密

void DES_ALG::DesEnter(string &Data_in,BITE **Data_Out, string key, int Mode, int dataLen=64) {
	//模式选择
	if (Mode == 1)
	{
		NumS = Data_in.size();
		//填充
		if (Data_in.size() % 8 != 0) {
			for (int i = 0; i < 8 - (NumS % 8); i++) {
				Data_in.push_back('C');
			}
		}
		cout << "填充数据:"<<Data_in << endl;
		GroupNum = Data_in.size() / 8;
		CreSubKey(key);
		//密文
		for (int i = 0; i < GroupNum; i++) {
			string GroupX = "";
			for (int j = 0; j < 8; j++) {
				GroupX.push_back(Data_in[i * 8 + j]);
			}
			cout << GroupX << endl;
			Enc_DES(Data_Out[i], GroupX);

		}
	}
	else {
		for (int i = 0; i < GroupNum; i++) {
			Dec_DES(Data_in, Data_Out[i]);
		}
		for (int i = 0; i < GroupNum * 8 - NumS; i++) {
			Data_in.pop_back();
		}
	}
}

int main() {
	string Mess_Out = "";
	//创建密文数组
	BITE** BITE_IO = new BITE * [N];
	for (int i = 0; i < N; i++) {
		BITE_IO[i] = new BITE[64];
	}
	//明文
	string Mes = "";
	cout << "请输入需要加密的明文:";
	getline(cin, Mes);
	//秘钥
	string key = "";
	cout << "请输入秘钥:";
	getline(cin, key);
	DES_ALG* DES = new DES_ALG;
	cout << "开始加密——" << endl;
	DES->DesEnter(Mes,BITE_IO, key, 1);

	cout <<"加密后的二进制密文是:"<<endl;
	for (int i = 0; i < DES->Get_GroupNUm();i++)
	{
			PrintBin(BITE_IO[i], 64);
	}
	DES->DesEnter(Mess_Out,BITE_IO, key, 0);
	cout << "解密后的结果:" << Mess_Out << endl;

	return 0;
}
  • Numbertables.h 文件存储不会改变的表
#ifndef _TABLES_H_    // 防重复编译 
#define _TABLES_H_

 // 对明文执行IP置换得到L0,R0 (L左32位,R右32位)               [明文操作]
 const char IP_Table[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
 };

 // 对迭代后的L16,R16执行IP逆置换,输出密文
const char IPR_Table[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
 };

 /*--------------------------- 迭代法则 ----------------------------*/

 // F函数,32位的R0进行E变换,扩为48位输出 (R1~R16)        [备用A]  [明文操作] 
static char 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
 };

 // 子密钥K(i)的获取 密钥为K 抛弃第6,16,24,32,40,48,64位          [密钥操作] 
 // 用PC1选位 分为 前28位C0,后28位D0 两部分  
static char 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
 };

 // 对C0,D0分别进行左移,共16次,左移位数与下面对应                 [密钥操作]
 static char Move_Table[16] = {
      1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
 };

 // C1,D1为第一次左移后得到,进行PC2选位,得到48位输出K1   [备用B]   [密钥操作]     
 static char 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,34,33,48,
     44,49,39,56,34,53,46,42,50,36,29,32
 };

 /*------------- F函数 备用A和备用B 异或 得到48位输出 ---------------*/

 // 异或后的结果48位分为8组,每组6位,作为8个S盒的输入             [组合操作] 
 // S盒以6位作为输入(8组),4位作为输出(4*(8组)=32位)
 // S工作原理 假设输入为A=abcdef ,则bcde所代表的数是0-15之间的
 // 一个数记为 X=bcde ,af代表的是0-3之间的一个数,记为 Y=af 
 // 在S1的X列,Y行找到一个数Value,它在0-15之间,可以用二进制表示
 // 所以为4bit (共32位)  
static char S_Box[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},
	}
};

// F函数 最后第二步,对S盒输出的32进行P置换                     [组合操作]
// 输出的值参与一次迭代:
// L(i)=R(i-1)
// R(i)=L(i-1)^f(R(i-1),K(i)) 异或 
 static char P_Table[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
 };

 // 16个子密钥K(1~16) 
 static bool SubKey[16][48] = { 0 };
 #endif

  • 代码参考https://www.cnblogs.com/ailx10/p/5303465.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阁下莫非东西

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

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

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

打赏作者

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

抵扣说明:

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

余额充值