⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 des.cpp

📁 实现简单的DES算法
💻 CPP
字号:
#include <fstream.h>
#include <math.h>
#include <string.h>
#include <conio.h>

//存放所有表的文件(次序跟下面声明顺序一样)
const char* alltables_file = "alltables.txt";

class DES
{
	public:
		DES(int skdata[]);			//以skdata来初始化密钥
		void SetPL(int pldata[]);	//置明文值
		void SetCI(int cidata[]);	//置密文值
		void GetPL(int pldata[]);	//获取明文
		void GetCI(int cidata[]);	//获取密文
		bool ReadTables();			//读表
		void Crypt();				//DES核心算法
		bool Encrypt();				//加密	返回是否加密成功
		bool Decrypt();				//解密	返回是否解密成功	

	private:
		int PL[64];			//明文
		int CI[64];			//密文
		int SK[64];			//密钥

		int L[17][32];		//一轮输入的左32位
		int R[17][32];		//一轮输入的右32位
		int C[17][28];		//一轮中密钥的左28位
		int D[17][28];		//一轮中密钥的右28位
		int K[17][48];		//一轮中参与异或的密钥
		
		int IPTable[64];	//初始置换表
		int IIPTable[64];	//逆初始置换表
		int ETable[48];		//扩充置换表
		int PTable[32];		//置换函数表

		int PC1Table[56];	//置换选择1表(密钥)
		int PC2Table[48];	//置换选择2表(密钥)
		int LBitTable[17];	//密钥每轮左移的位数表

		int SBoxsTable[8][64];	//S盒表
};

DES::DES(int skdata[])
{
	for(int i=0; i<64; i++)
		SK[i] = skdata[i];
}

void DES::SetPL(int pldata[])
{
	for(int i=0; i<64; i++)
		PL[i] = pldata[i];
}

void DES::SetCI(int cidata[])
{
	for(int i=0; i<64; i++)
		CI[i] = cidata[i];
}

void DES::GetPL(int pldata[])	
{	
	for(int i=0; i<64; i++)
		pldata[i] = PL[i];
}

void DES::GetCI(int cidata[])	
{	
	for(int i=0; i<64; i++)
		cidata[i] = CI[i];
}

bool DES::ReadTables()					//读表程序	
{										//输入:同文件目录下的alltables.txt
	ifstream input_file;				//输出:为所有类成员表赋值,出错返回false,否则为true
	char Tnames[20];					//表的名字(读入它用于过滤表中名字说明)
	int i;

	input_file.open(alltables_file);
	if(!input_file)						//打不开文件
	{
		cout<<"Can not open alltables file!"<<endl;
		return false;
	}

	input_file>>Tnames;
	for(i=0; i<64; i++) 
	{
		input_file>>IPTable[i];			//读入初始置换表
		IPTable[i]--;					//把表中数据(1-64)转化为下标(0-63)
	}
	input_file>>Tnames;
	for(i=0; i<64; i++) 
	{
		input_file>>IIPTable[i];		//读入逆初始置换表
		IIPTable[i]--;					//把表中数据(1-64)转化为下标(0-63)
	}
	input_file>>Tnames;
	for(i=0; i<48; i++) 
	{
		input_file>>ETable[i];			//读入扩充置换表
		ETable[i]--;					//把表中数据(1-48)转化为下标(0-47)
	}
	input_file>>Tnames;
	for(i=0; i<32; i++) 
	{
		input_file>>PTable[i];			//读入置换函数表
		PTable[i]--;					//把表中数据(1-32)转化为下标(0-31)
	}
	input_file>>Tnames;
	for(i=0; i<56; i++) 
	{
		input_file>>PC1Table[i];		//读入置换选择1表
		PC1Table[i]--;					//把表中数据(1-56)转化为下标(0-55)
	}
	input_file>>Tnames;
	for(i=0; i<48; i++) 
	{
		input_file>>PC2Table[i];		//读入置换选择2表
		PC2Table[i]--;					//把表中数据(1-48)转化为下标(0-47)
	}

	input_file>>Tnames;
	for(i=1; i<17; i++) 
		input_file>>LBitTable[i];		//读入密钥每轮左移的位数表 注意第0轮不用,下标1-16有用
	
	input_file>>Tnames;
	for(i=0; i<8; i++) 
		for(int j=0; j<64; j++)			//读入S盒表
			input_file>>SBoxsTable[i][j];	
										
	input_file.close();
	return true;
}

void DES::Crypt()
{
	int i,j;							//用于循环计数(i主要用于轮数)	
	int T_ER[17][48];					//右明文扩充置换之后的暂存数组
	int T_RK[17][48];					//T_ER与K异或之后的暂存数组
	int T_SRK[17][32];					//T_RK经S盒代换之后的暂存数组
	int T_PSRK[17][32];					//T_SRK经P置换之后的暂存数组

	for(i=1; i<=16; i++)				//开始16轮加密过程
	{								
		for(j=0; j<32; j++)				//第一步:Li = Ri-1
			L[i][j] = R[i-1][j];
		
		for(j=0; j<48; j++)				//第二步:扩充置换******
			T_ER[i][j] = R[i-1][ETable[j]];

		for(j=0; j<48; j++)				//第三步:PC-2置换******
		{
			if(PC2Table[j] < 28)	K[i][j] = C[i][PC2Table[j]];
			else					K[i][j] = D[i][PC2Table[j]-28];
		}

		for(j=0; j<48; j++)				//第四步:T_ER与K异或******
			T_RK[i][j] = (T_ER[i][j] + K[i][j]) % 2;

		int x=0, y=0;					//第五步:S盒代换******
		for(int box=0; box<8; box++)	//x,y分别是每经一盒对应于T_RK和T_SRK要平移的位数
		{
			int row, col, value;		//求出在S表中的行和列、以及对应坐标得出的S盒的值

			row = T_RK[i][x]*2 + T_RK[i][x+5];
			col = T_RK[i][x+1]*8 + T_RK[i][x+2]*4
				+ T_RK[i][x+3]*2 + T_RK[i][x+4];
			
			value = SBoxsTable[box][row*16 + col];

			for(int bt=0; bt<4; bt++)	//将value转化为二进制并赋值给T_SRK
			{
				int tpow = (int)pow(2, (3-bt));
				T_SRK[i][bt+y] = value / tpow;
				value = value % tpow;
			}

			x += 6;		y += 4;
		}

		for(j=0; j<32; j++)				//第六步:P置换******
			T_PSRK[i][j] = T_SRK[i][PTable[j]];

		for(j=0; j<32; j++)				//第七步:T_PSRK与Li-1异或******
			R[i][j] = (T_PSRK[i][j] + L[i-1][j]) % 2;
	}
}

bool DES::Encrypt()
{
	if(!ReadTables())					//数据读入失败
	{
		cout<<"Error! Data Loaded Fail!"<<endl;
		return false;
	}

	int i;
	int T_IPPL[64];						//明文初始置换之后的暂存数组
	int T_PC1SK[56];					//密钥经PC1置换之后的暂存数组

	for(i=0; i<64; i++)					//******初始置换******
		T_IPPL[i] = PL[IPTable[i]];
		
	for(i=0; i<32; i++)					//给L0与R0赋初值
	{
		L[0][i] = T_IPPL[i];
		R[0][i] = T_IPPL[i+32];
	}	
	
	for(i=0; i<56; i++)					//******PC-1置换******	
		T_PC1SK[i] = SK[PC1Table[i]];

	for(i=0; i<28; i++)					//给C0与D0赋初值
	{
		C[0][i] = T_PC1SK[i];
		D[0][i] = T_PC1SK[i+28];
	}

	for(i=1; i<=16; i++)
	{
		for(int j=0; j<LBitTable[i]; j++)	//******各轮密钥生成******
		{
			for(int kk=0; kk<27; kk++)		//本轮密钥左移LBitTable[i]位
			{
				C[i][kk] = C[i-1][kk+1];
				D[i][kk] = D[i-1][kk+1];
			}
			C[i][27] = C[i-1][0];
			D[i][27] = D[i-1][0];
		}
	}

	Crypt();							//******16轮DES核心算法******

	for(i=0; i<64; i++)					//******把L16与R16交换后的值赋给准密文******
	{
		if(i<32) CI[i] = R[16][i];
		else	 CI[i] = L[16][i-32];
	}
	return true;
}

bool DES::Decrypt()
{
	if(!ReadTables())					//数据读入失败
	{
		cout<<"Error! Data Loaded Fail!"<<endl;
		return false;
	}

	int i;
	int T_PC1SK[56];					//密钥经PC1置换之后的暂存数组
	int T_PL[64];						//准明文(还差逆初始置换)

	for(i=0; i<32; i++)					//给L0与R0赋初值
	{
		L[0][i] = CI[i];
		R[0][i] = CI[i+32];
	}	
	
	for(i=0; i<56; i++)					//******PC-1置换******	
		T_PC1SK[i] = SK[PC1Table[i]];

	for(i=0; i<28; i++)					//给C0与D0赋初值
	{
		C[0][i] = T_PC1SK[i];
		D[0][i] = T_PC1SK[i+28];
	}

	for(i=16; i>=1; i--)
	{
		for(int j=0; j<LBitTable[i]; j++)	//******各轮密钥生成******
		{
			for(int kk=0; kk<27; kk++)		//本轮密钥左移LBitTable[i]位
			{
				if(i == 16)					//注意与加密密码下标反转(除第0个)
				{
					C[16][kk] = C[0][kk+1];	
					D[16][kk] = D[0][kk+1];
				}
				else{
					C[i][kk] = C[i+1][kk+1];
					D[i][kk] = D[i+1][kk+1];
				}
			}
			if(i == 16)
				{
					C[16][27] = C[0][0];
					D[16][27] = D[0][0];
				}
				else{
					C[i][27] = C[i+1][0];
					D[i][27] = D[i+1][0];
				}
		}
	}

	Crypt();							//******16轮DES核心算法******

	for(i=0; i<64; i++)					//******把L16与R16交换后的值赋给准明文******
	{
		if(i<32) T_PL[i] = R[16][i];
		else	 T_PL[i] = L[16][i-32];
	}

	for(i=0; i<64; i++)					//******准明文的逆初始置换******
		PL[i] = T_PL[IIPTable[i]];

	return true;
}

int* CharstoBits(int NN, char chs[])	//把一个字符串转化为ASCII码串
{
	int n = NN * 8;						//每个字符占8位
	int* bs = new int [n+1];
	int tvalue, tpow, x=0;

	for(int i=0; i<NN; i++)
	{
		tvalue = (int) chs[i];			//求字符对应的ASCII码的十进制值
		for(int j=0; j<8; j++)			//十进制转化为二进制串
		{
			tpow = (int)pow(2, (7-j));
			bs[x+j] = tvalue / tpow;
			tvalue = tvalue % tpow;
		}
		x += 8;
	}
	bs[n] = '\0';
	return bs;
}

char* BitstoChars(int NN, int bs[])		//把一个ASCII码串转化为字符串
{
	int n = NN / 8;						//每个字符占8位
	char* chs = new char [n+1];
	int tvalue, x=0;

	for(int i=0; i<n; i++)
	{
		tvalue=0;
		for(int j=0; j<8; j++)
			tvalue += (int)bs[x+j] * pow(2, 7-j);	//求出此ASCII码对应的十进制值
		chs[i] = (char)tvalue;						//将此值转为字符类型
		x += 8;
	}
	chs[n] = '\0';
	return chs;
}


/***********************DEMO2***************************/
void main()								//显示程序
{
	int* plain;							//输入的明文指针
	int* skey;							//输入的密钥指针
	int plshow[65];						//明文ASCII码数组
	int cishow[64];						//密文ASCII码数组
	int dplshow[65];					//解出的密文ASCII码数组

	int i, num;							//用于循环和计数
	char* chshow;						//用于显示字符串
	char ch[8];							//用于输入暂存

	cout<<"***正在运行DES加解密显示程序***"<<endl<<endl;
	do{
		cout<<"请输入要加密的串(8个字符):";
		cin>>ch;
	}while(strlen(ch) != 8);			//串长必须为8个字符
	plain = CharstoBits(8, ch);			//转化为ASCII码串并作为明文输入

	cout<<endl;
	do{
		cout<<"请输入要密钥(8个字符):";
		cin>>ch;
	}while(strlen(ch) != 8);			//串长必须为8个字符
	skey = CharstoBits(8, ch);			//转化为ASCII码串并作为密钥输入
	skey[64] = '\0';

	DES en(skey);						//加密过程	初始化数据
	en.SetPL(plain);
	en.GetPL(plshow);
	plshow[64] = '\0';

	cout<<endl<<"密钥(ASCII码):";		//显示密钥(ASCII码)
	for(num=0, i=0; i<64; i++)
	{
		if(num%8 == 0) cout<<endl;
		cout<<skey[i]<<" * ";
		num++;
	}

	cout<<endl<<"明文(ASCII码):";		//显示明文(ASCII码)
	for(num=0, i=0; i<64; i++)
	{
		if(num%8 == 0) cout<<endl;
		cout<<plshow[i]<<" * ";
		num++;
	}

	if( !en.Encrypt() )					//加密失败
	{
		cout<<endl<<"!!!!!!加密失败!!!!!!"<<endl;
		return;
	}
	en.GetCI(cishow);					//加密成功 获取密文
	
	cout<<endl<<"\n.........加密中.........\n";
	cout<<endl<<"密文:";				//显示密文串
	chshow = BitstoChars(64, cishow);
	cout<<chshow;
	cout<<endl<<"密文(ASCII码):";		//显示密文(ASCII码)
	for(num=0, i=0; i<64; i++)
	{
		if(num%8 == 0) cout<<endl;
		cout<<cishow[i]<<" * ";
		num++;
	}


	DES de(skey);						//解密过程
	de.SetCI(cishow);
	if( !de.Decrypt() )					//解密失败
	{
		cout<<endl<<"!!!!!!解密失败!!!!!!"<<endl;
		return ;
	}
	de.GetPL(dplshow);					//解密成功 获取明文

	cout<<endl<<"\n.........解密中.........\n";
	cout<<endl<<"明文:";				//显示明文
	chshow = BitstoChars(64, dplshow);
	cout<<chshow;
	cout<<endl;
	cout<<"Press any key to Quit "<<endl;
	getch();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -