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

📄 des1.h

📁 DES算法的C语言实现
💻 H
字号:
/*DES 算法c语言实现函数 	编写者 	王晓峰 	2002年11月,
	这是我的一个练习函数,在此函数的编写调试过程中我发现一个错误:
	在IP_1变换过程中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};	此IP_1变换换位表错误!!


但调试不能通过,后我通过手工反演计算发现将此表做如下调整可得正确结果,即将1、2,3、4,5、6,7、8列对调。
现将调整后结果给出如下:

     	int IP_1[64]={   8,40,16,48,24,56,32,64,
			 7,39,15,47,23,55,31,63,
			 6,38,14,46,22,54,30,62,
			 5,37,13,45,21,53,29,61,
			 4,36,12,44,20,52,28,60,
			 3,35,11,43,19,51,27,59,
			 2,34,10,42,18,50,26,58,
			 1,33, 9,41,17,49,25,57};	


								王晓峰
								2002.11.25				
		
*/


void BittoByte(char p[8],char Data[64])
/*
将原始数据位扩展为字节,
char 	p[8]	原始8字节数组,
char 	data[64]扩展目标数组,内容为0或1,
char 	temp	临时字符,
int 	i	工作变量字符数组下标,
int	j	工作变量i所指字符的位标。
*/
{
char 	temp;
int 	i,j;
for(i=0;i<64;i++)
	{
	j=i%8;
	temp=p[i/8];
	temp=temp<<j;
	Data[i]=temp>>7;
	if (Data[i]==-1)  Data[i]=1;
	}
}


void BittoByte_48(char p[6],char Data[48])
/*
将原始数据位扩展为字节,
char 	p[8]	原始8字节数组,
char 	data[64]扩展目标数组,内容为0或1,
char 	temp	临时字符,
int 	i	工作变量字符数组下标,
int	j	工作变量i所指字符的位标。
*/
{
char 	temp;
int 	i,j;
for(i=0;i<48;i++)
	{
	j=i%8;
	temp=p[i/8];
	temp=temp<<j;
	Data[i]=temp>>7;
	if (Data[i]==-1)  Data[i]=1;
	}
}
void BytetoBit(char p[8],char Data[64])
/*
将以64字节表示的位组压缩为8字节数组,
char	p[8]	目标8字节数组,
char	Data[64]原始64位比特位组,
int 	i 	工作变量位组下标,
*/
{
int 	i;
for(i=0;i<8;i++)
	p[i]=0;
for(i=0;i<64;i++)
	{
	p[i/8]=p[i/8]+Data[i];
	if(i%8!=7) p[i/8]=p[i/8]*2;
	}
}




void IntitalPermutation(char Data[64],char L[32],char R[32]) 
/* 
初始排列函数,
int 	IP[64]  初始排列法,0-63位,使用时 IP[i]-1,
char 	Data[64]明文代码, 0-63位,
char 	L[32]	IP排列后前32位代码 0-31位,
char 	R[32] 	IP排列后后32位代码 0-31位,
int 	i 	工作变量.
*/
{
int 	IP[64]={58,50,42,34,26,18,10,02,
		60,52,44,36,28,20,12,04,
		62,54,46,38,30,22,14,06,
		64,56,48,40,32,24,16, 8,	
		57,49,41,33,25,17, 9,01,
		59,51,43,35,27,19,11,03,
		61,53,45,37,29,21,13,05,
		63,55,47,39,31,23,15,07};
int 	i;
for(i=0;i<64;i++)
	if 	(i<32) L[i]=Data[IP[i]-1];
	else	R[i-32]=Data[IP[i]-1];
	
}


void Expand(char Data1[32],char Data2[48])
/*
扩展转换 32位->48位,
char	Data1[32]原始32位代码,
char	Data2[48]扩展后的48位代码,
int	i	 工作变量 Data1 各位的下标,	
int 	Exp[48]	 扩展置换表,使用时Exp[i]-1.
*/
{
int 	Exp[48]={	32,01,02,03,04,05,
			04,05,06,07, 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,01};

int	i;
for(i=0;i<48;i++)
	Data2[i]=Data1[Exp[i]-1];
}


void Compressedencoding(char Data1[48],char Data2 [32])
/*压缩48位->32位,
char 	Data1[48]	输入48位位组,
char	Data2[32]	输出32位位组,
char	string[4]	4字节字符数组存放中间结果,
char	temp		临时工作变量,
int	S[8][4][16]	S盒8组每组4行16列,
int 	hang[8]		S盒的行号,
int 	lei[8]		S盒的列号,
int 	i		临时工作变量,
int 	j		临时工作变量.
*/
{
char	string[4];
char	temp;
int 	hang[8],lei[8];
int 	i,j;
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,05,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},
			};


for(i=0;i<8;i++)	
	{
	hang[i]=Data1[i*6]*2+Data1[i*6+5];
	lei[i]=Data1[i*6+1]*8+Data1[i*6+2]*4+Data1[i*6+3]*2+Data1[i*6+4];
	}

for(i=0;i<4;i++)
	{
	string[i]=(S[i*2][hang[i*2]][lei[i*2]]*16+S[i*2+1][hang[i*2+1]][lei[i*2+1]]);
	}
for(i=0;i<32;i++)
	{
	j=i%8;
	temp=string[i/8];
	temp=temp<<j;
	Data2[i]=temp>>7;
	if (Data2[i]==-1)  Data2[i]=1;
	}
}


void Pchang(char Data1[32],char Data2[32])
/* P排列换位表变换,
char 	Data1[32]	输入32位位组,
char	Data2[32]	输出32位位组,
int 	p[32]		换位表使用时p[i]-1,
int 	i		临时工作变量。
*/
{
int 	p[32]={	16,07,20,21,
		29,12,28,17,
		01,15,23,26,
		05,18,31,10,
		02, 8,24,14,
		32,27,03, 9,
		19,13,30,06,
		22,11,04,25};
int 	i;
for(i=0;i<32;i++)
	Data2[i]=Data1[p[i]-1];
}


void Intitalpermutation_1(char Data[64],char L[32],char R[32])
/* Ip_1变换,
char 	Data[64]输出64位组,	
char	L[32]	输入的前半部32位位组,
char	R[32]	输入的后半部32位位组,
char	temp[64]临时工作数组,
int	IP_1[64]	IP_1换位表,使用时IP_1[i]-1,
int	i	临时工作变量。
*/		
{
/*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};此IP_1变换换位表错误!!!!!!!!!	*/


int	IP_1[64]={	 8,40,16,48,24,56,32,64,
			 7,39,15,47,23,55,31,63,
			 6,38,14,46,22,54,30,62,
			 5,37,13,45,21,53,29,61,
			 4,36,12,44,20,52,28,60,
			 3,35,11,43,19,51,27,59,
			 2,34,10,42,18,50,26,58,
			 1,33, 9,41,17,49,25,57};	

char	temp[64];
int i;
for(i=0;i<64;i++)
	{
	if(i<32) temp[i]=L[i];
	else temp[i]=R[i-32];
	}

for(i=0;i<64;i++)
	Data[i]=temp[IP_1[i]-1];


}
	
	
void Mishi(char Data[64],char Mishi[16][48])
/*生成16个48位密钥,
char 	Data[64]	原始64位密钥明文,
char	Mishi[16][48]	存放生成的16个48位子密钥,
char	C[28],D[28]	两个28位循环左移位组,
char 	temp[56]	临时工作数组,存放56位中间结果位组,
char	temp_c		临时工作变量,
char	temp_d		临时工作变量,
int	PC_1_c[28]	原始64位密钥明文去掉校验位后的前28位,使用时PC_2[i]-1,
int 	PC_1_d[28]	原始64位密钥明文去掉校验位后的后28位,使用时PC_2[i]-1,
int 	PC_2[48]	56位中48位子集换位表,使用时PC_2[j]-1,
int 	LS[16]		16次循环左移位数表,
int 	i,j,k		临时工作变量,
*/
{
int	PC_1_c[28]={	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};

int 	PC_1_d[28]={	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 	LS[16]={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};

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};	
char	C[28],D[28];
char 	temp[56];	
char	temp_c;
char	temp_d;
int 	i,j,k;
for(i=0;i<28;i++)
	{
	C[i]=Data[PC_1_c[i]-1];
	D[i]=Data[PC_1_d[i]-1];
	}

for(i=0;i<16;i++)
	{
	for(j=LS[i];j>0;j--)				/*循环左移*/
		{
		temp_c=C[0];
		temp_d=D[0];
		for(k=0;k<27;k++)			/*循环左移1位*/
			{
			C[k]=C[k+1];
			D[k]=D[k+1];		
			}
		C[27]=temp_c;
		D[27]=temp_d;
		}

	for(j=0;j<56;j++)
		{
		if(j<28)
			temp[j]=C[j];
		else   	temp[j]=D[j-28];
		}

	for(j=0;j<48;j++)
		{
		Mishi[i][j]=temp[PC_2[j]-1];
		}
  
	}
}

void Des(char string1[8],char string2[8],int flag,int flag2)
/*DES 标准算法加密解密函数,
char 	string1[8]	输入的8字节明文或密文,
char 	string2[8]	输入的8字节原始密钥,
char	Data1[64]	扩展的64位明文或密文位组,
char	Data2[64]	扩展的64位原始密钥位组,
char	Miyao[16][48]	16个子密钥的48位位组,
char	L[32],R[32]	明文或密文的前32位位组和后32位位组,
char 	Expand_data[48]	由32位扩展而成的48位位组,
char 	temp1[32]	临时工作32位位组,
char 	temp2[32]	临时工作32位位组,
int	flag		加解密标志:flag==0为加密,反之为解密,
int	flag2		是否重新计算子密钥,flag==0为计算,反之为不计算.
ing 	i,j		临时工作变量。
*/	
{
char	Data1[64];	
char	Data2[64];
static	char	Miyao[16][48];	
char	L[32],R[32];	
char 	Expand_data[48];
char 	temp1[32];	
char 	temp2[32];	
int 	i,j;	
BittoByte(string1,Data1);	/*比特至字节的转换*/
BittoByte(string2,Data2);	/*比特至字节的转换*/
IntitalPermutation(Data1,L,R);	/*IP变换*/
if (flag2==0)	Mishi(Data2,Miyao);		/*密匙生成*/

if(flag==0)			/*加密过程*/
	{
	for(i=0;i<16;i++)
		{
		Expand(R,Expand_data);				/*右半部32位扩展为48位*/
	
		for(j=0;j<48;j++)					/*与子密钥异或*/
			{
			Expand_data[j]=Expand_data[j]^Miyao[i][j];		
			}

		Compressedencoding(Expand_data,temp1);		/*压缩48位为32位*/

		Pchang(temp1,temp2);				/*P变换*/
		for(j=0;j<32;j++)					/*与左半部异或*/
			{
			temp2[j]=temp2[j]^L[j];
			}

		for(j=0;j<32;j++)					/*右半部放入左半部,右半部存入上步异或结果*/
			{
			L[j]=R[j];
			R[j]=temp2[j];
			}
		}
	Intitalpermutation_1(Data1,L,R);				/*IP-1变换*/

	BytetoBit(string1,Data1);					/*字节转换为比特*/

	}
else									/*解密过程*/
	{
	for(i=15;i>-1;i--)
		{
		Expand(R,Expand_data);				/*右半部32位扩展为48位*/
		
		for(j=0;j<48;j++)					/*与子密钥异或*/
			{
			Expand_data[j]=Expand_data[j]^Miyao[i][j];		
			}

		Compressedencoding(Expand_data,temp1);		/*压缩48位为32位*/

		Pchang(temp1,temp2);				/*P变换*/

		for(j=0;j<32;j++)					/*与左半部异或*/
			{
			temp2[j]=temp2[j]^L[j];
			}

		for(j=0;j<32;j++)					/*右半部放入左半部,右半部存入上步异或结果*/
			{
			L[j]=R[j];
			R[j]=temp2[j];
			}

		}
	Intitalpermutation_1(Data1,L,R);				/*IP-1变换*/
	BytetoBit(string1,Data1);					/*字节转换为比特*/

	}	

}

⌨️ 快捷键说明

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