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

📄 des.cpp

📁 des加密算法 des加密算法 des加密算法 解密
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 #include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define BYTE   unsigned char
#define LPBYTE   BYTE* 
#define LPCBYTE   const BYTE* 
#define BOOL   int 


class DES 
{ 
public: 
	BOOL CDesEnter(LPCBYTE in, LPBYTE out, int datalen, const BYTE key[8], BOOL type);
	BOOL CDesMac(LPCBYTE mac_data, LPBYTE mac_code, int datalen, const BYTE key[8]);  
	LPBYTE Bin2ASCII(const BYTE byte[64], BYTE bit[8]);  
	LPBYTE ASCII2Bin(const BYTE bit[8], BYTE byte[64]);  
private: 
	int i;
	void XOR(const BYTE in1[8], const BYTE in2[8], BYTE out[8]);  
	void GenSubKey(const BYTE oldkey[8], BYTE newkey[16][8]); 
	void endes(const BYTE m_bit[8], const BYTE k_bit[8], BYTE e_bit[8]);  
	void undes(const BYTE m_bit[8], const BYTE k_bit[8], BYTE e_bit[8]);   
	void SReplace(BYTE s_bit[8]);
}des; 

/*   
*   CDesEnter 函数说明:
*     des加密/解密入口 
*   返回:
*     1则成功,0失败 
*   参数: 
*     in 需要加密或解密的数据
*         注意:in缓冲区的大小必须和datalen相同. 
*     out 加密后或解密后输出。
*         注意:out缓冲区大小必须是8的倍数而且比datalen大或者相等。 
*         如datalen=7,out缓冲区的大小应该是8,datalen=8,out缓冲区的大小应该是8,
*         datalen=9,out缓冲区的大小应该是16,依此类推。  
*     datalen 数据长度(字节)。 
*         注意:datalen 必须是8的倍数。 
*     key 8个字节的加密或解密的密码。
*     type 是对数据进行加密还是解密 
*         0 表示加密 1 表示解密 
*/
BOOL DES::CDesEnter(LPCBYTE in, LPBYTE out, int datalen, const BYTE key[8], BOOL type)
{ 
	//判断输入参数是否正确,失败的情况为: 
	//!in: in指针(输入缓冲)无效 
	//!out: out指针(输出缓冲)无效
	//datalen<1: 数据长度不正确 
	//!key: 加/解密密码无效
	//type && ((datalen % 8) !=0:选择解密方式但是输入密文不为8的倍数 
	if((!in) || (!out) || (datalen<1) || (!key) || (type && ((datalen % 8) !=0))) 
		return false; 

	int i;
	if(type==0) //选择的模式是加密 
	{ 
		// 用于存储待加密字串最后的若干字节 
		// DES算法是以8个字节为单位进行加密,如果待加密字串以8为单位分段加密时,最后一段不足
		//8字节,则在后面补0,使其最后一段的长度为8字节 
		// te8bit是作为存储待加密字串最后一段(不足8字节)的变量 
		BYTE te8bit[8]={0,0,0,0,0,0,0,0}; 

		// 这是待加密字串的调整长度 
		// 如果原始长度是8的整数倍,则调整长度的值和原来的长度一样 
		// 如果原始长度不是8的整数倍,则调整长度的值是能被8整除且不大于原来长度的最大整数。   
		//也就是不需要补齐的块的总长度。 
		int te_fixlen = datalen - (datalen % 8); 

		// 将待加密密文以8为单位分段,把最后长度不足8的一段存储到te8bit中。
		for(i = 0; i < (datalen % 8); i++)
			te8bit[i] = in[te_fixlen + i];
		// 将待加密字串分以8字节为单位分段加密
		for(i = 0; i < te_fixlen; i += 8) 
			endes(in + i, key, out + i);

		// 如果待加密字串不是8的整数倍,则将最后一段补齐(补0)后加密
		if(datalen % 8 != 0)
			endes(te8bit, key, out + datalen / 8 * 8); 
	}  
	else   //选择的模式是解密 
	{ 
		// 将密文以8字节为单位分段解密 
		for(int i = 0; i < datalen; i += 8) 
			undes(in + i, key, out + i); 
	}
	return true;
} 

/* 
*   XOR 函数说明: 
*     将输入的两个8字节字符串异或 
*   返回:
*     无 
*   参数:
*     const BYTE in1[8] 输入字符串1 
*     const BYTE in2[8] 输入字符串2 
*     BYTE out[8] 输出的结果字符串     
*/
void DES::XOR(const BYTE in1[8], const BYTE in2[8], BYTE out[8]) 
{
	for(int i = 0; i < 8; i++) 
		out[i] = in1[i] ^ in2[i]; 
}

/* 
*   Bin2ASCII 函数说明:
*     将64字节的01字符串转换成对应的8个字节
*   返回: 
*     转换后结果的指针 
*   参数: 
*     const BYTE byte[64] 输入字符串 
*     BYTE bit[8] 输出的转换结果     
*/
LPBYTE DES::Bin2ASCII(const BYTE byte[64], BYTE bit[8])
{ 
	for(int i = 0; i < 8; i++) 
	{
		bit[i] = byte[i * 8] * 128 + byte[i * 8 + 1] * 64 + 
			byte[i * 8 + 2] * 32 + byte[i * 8 + 3] * 16 + 
			byte[i * 8 + 4] * 8 + byte[i * 8 + 5] * 4 + 
			byte[i * 8 + 6] * 2 + byte[i * 8 + 7];
	} 
	return bit; 
} 

/* 
*   ASCII2Bin 函数说明:
*     将8个字节输入转换成对应的64字节的01字符串
*   返回: 
*     转换后结果的指针 
*   参数:
*     const BYTE bit[8] 输入字符串 
*     BYTE byte[64] 输出的转换结果     
*/ 
LPBYTE DES::ASCII2Bin(const BYTE bit[8], BYTE byte[64])
{ 
	for(int i=0; i < 8; i++) 
		for(int j = 0; j < 8; j++) 
			byte[i * 8 + j] = ( bit[i] >> (7 - j) ) & 0x01; 
	return byte; 
} 

/* 
*   GenSubKey 函数说明:
*     由输入的密钥得到16个子密钥 
*   返回: 
*     无 
*   参数: 
*     const BYTE oldkey[8] 输入密钥
*     BYTE newkey[16][8] 输出的子密钥
*/ 
void DES::GenSubKey(const BYTE oldkey[8], BYTE newkey[16][8]) 
{ 
	int i, k, rol = 0;
	//缩小换位表1 
	int pc_1[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}; 
	//缩小换位表2
	int pc_2[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}; 
	//16次循环左移对应的左移位数 
	int ccmovebit[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};

	BYTE oldkey_byte[64]; 
	BYTE oldkey_byte1[64];
	BYTE oldkey_byte2[64]; 
	BYTE oldkey_c[56];
	BYTE oldkey_d[56]; 
	BYTE newkey_byte[16][64];

	ASCII2Bin(oldkey, oldkey_byte); 

	//位变换 
	for(i = 0; i < 56; i++)
		oldkey_byte1[i] = oldkey_byte[pc_1[i] - 1];
	//分为左右两部分,复制一遍以便于循环左移
	for(i = 0; i < 28; i++)
		oldkey_c[i] = oldkey_byte1[i], oldkey_c[i + 28] = oldkey_byte1[i], 
		oldkey_d[i] = oldkey_byte1[i + 28], oldkey_d[i + 28] = oldkey_byte1[i + 28]; 

	//分别生成16个子密钥 
	for(i = 0; i < 16; i++) 
	{
		//循环左移 
		rol += ccmovebit[i];
		//合并左移后的结果 
		for(k = 0; k < 28; k++) 
			oldkey_byte2[k] = oldkey_c[k + rol], oldkey_byte2[k + 28] = oldkey_d[k + rol]; 
		//位变换 
		for(k = 0; k < 48; k++) 
			newkey_byte[i][k] = oldkey_byte2[pc_2[k] - 1]; 

	}   
	//生成最终结果 
	for(i = 0; i < 16; i++) 
		Bin2ASCII(newkey_byte[i], newkey[i]);
}

/* 
*   endes 函数说明: 
*     DES加密 
*   返回: 
*     无
*   参数: 
*     const BYTE m_bit[8] 输入的原文
*     const BYTE k_bit[8] 输入的密钥
*     BYTE e_bit[8] 输出的密文 
*/  
void DES::endes(const BYTE m_bit[8], const BYTE k_bit[8], BYTE e_bit[8]) 
{ 
	//换位表IP
	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
	}; 
	//换位表IP_1
	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 
	}; 
	BYTE m_bit1[8] = {0};
	BYTE m_byte[64] = {0}; 
	BYTE m_byte1[64] = {0}; 
	BYTE key_n[16][8] = {0};
	BYTE l_bit[17][8] = {0}; 
	BYTE r_bit[17][8] = {0};
	BYTE e_byte[64] = {0};
	BYTE e_byte1[64] = {0}; 
	BYTE r_byte[64] = {0};
	BYTE r_byte1[64] = {0};
	int i, j; 

	//根据密钥生成16个子密钥 
	GenSubKey(k_bit, key_n); 
	//将待加密字串变换成01串
	ASCII2Bin(m_bit, m_byte);
	//按照ip表对待加密字串进行位变换
	for(i = 0; i < 64; i++)
		m_byte1[i] = m_byte[ip[i] - 1];
	//位变换后的待加密字串
	Bin2ASCII(m_byte1, m_bit1); 
	//将位变换后的待加密字串分成两组,分别为前4字节L和后4字节R,作为迭代的基础(第0次迭代) 
	for(i=0;i<4;i++)
		l_bit[0][i] = m_bit1[i], r_bit[0][i] = m_bit1[i + 4]; 
	//16次迭代运算 
	for(i = 1; i <= 16; i++) 
	{
		//R的上一次的迭代结果作为L的当前次迭代结果 
		for(j = 0; j < 4; j++) 
			l_bit[i][j] = r_bit[i-1][j]; 
		ASCII2Bin(r_bit[i-1], r_byte); 
		//将R的上一次迭代结果按E表进行位扩展得到48位中间结果
		for(j = 0; j < 48; j++)
			r_byte1[j] = r_byte[e[j] - 1]; 
		Bin2ASCII(r_byte1, r_bit[i-1]);

		//与第I-1个子密钥进行异或运算 
		for(j = 0; j < 6; j++) 
		{
			r_bit[i-1][j] = r_bit[i-1][j] ^ key_n[i-1][j]; 
		}

		//进行S选择,得到32位中间结果 

⌨️ 快捷键说明

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