DES加密算法实现过程

时间:2022-12-30 19:03:53
 
/*64位明文A,64位密钥key,64位密文B(本程序A加密10000次,每次密钥都是随机生成的,看是否能得到B)
总过程:明文经IP变换后分高低32位l0,r0,再经过16次循环加密得到r0l0,再IP逆变换得到密文。
其中1、IP变换和IP逆变换都是数组对应
2、16次循环的每次输入l0,r0输出l1,r1,本次输出是下一次的输入。每一次l1=r0,r1=l0^f(r0,ki)
而f(r0,ki)的过程是:r032to48^ki48,48位分成8组,每组6位,经过s压缩每组变为4位。得到的32位就是r1
另外16个ki的形成过程是:key64to56,分成两个28位c0,d0。接着16次循环,每次循环c0,d0分别按照一定的位数循环左移过后得到c1,d1再组合成一个key,而c1,d1成为下次的c0,d0
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define   RAND_MAX  0x7fffffffffffffffu

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 r32to48[48]={31,0,1,2,3,4,3,4,5,6,7,8,7,8,9,10,11,12,11,12,13,14,15,16,15,16,17,18,19,20,19,20,21,22,23,24,23,24,25,26,27,28,27,28,29,30,31,0};
int s[8][64]={{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}};

int key64to56[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 key56to48[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};

int left[16]={1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};

int main()
{
	freopen("des.txt","w+",stdout);
	unsigned __int64 A=0,B=1206425,rB,KEY,sum,kkey;
	int a[64]={0},b[64]={0},key[64],keyk[16][48],c0[28],d0[28],c0d0[56],IPa[64],after16[64],IP_1a[64],l0[32],r0[32],r048[48],r032[32],l1[32],r1[32];
	int num,i,j,k,group,everyGroup,lleft[10],x,y,fb[6];
	bool flag=false;
	
	//将所有的下标从0开始
	for(i=0;i<64;i++)
		IP[i]=IP[i]-1,IP_1[i]=IP_1[i]-1;
	for(i=0;i<48;i++)
		key56to48[i]=key56to48[i]-1;
	for(i=0;i<56;i++)
		key64to56[i]=key64to56[i]-1;
	//将A分成64位
	for(i=0;i<64;i++)
		a[i]=0;

	for(i=0;A;i++)
	{
		a[i]=A&1;
		A=A>>1;
	}
	//IP变换
	for(i=0;i<64;i++)
		IPa[i]=a[IP[i]];
	//左右各32位
	for(i=0;i<32;i++)
		l0[i]=IPa[i],r0[i]=IPa[i+32];

	//sum=0;
	//for(i=0;i<64;i++)
	//	sum=sum+((unsigned __int64)1<<i);
	//暴力枚举密钥
	for(num=0;num<10000;num++)
	{
		KEY=rand();
		//将KEY分解为64位
		for(i=0;i<64;i++)
			key[i]=0;
		i=0,kkey=KEY;
		while(kkey)
		{
			key[i++]=kkey&1;
			kkey=kkey>>1;
		}
		//64位降为56位
		for(i=0;i<28;i++)
			c0[i]=key[key64to56[i]],d0[i]=key[key64to56[i+28]];
		//key分为16个子密钥
		for(i=0;i<16;i++)
		{
			//c0,d0左移left[i]位
			for(j=0;j<left[i];j++)
				lleft[j]=c0[j];
			for(j=0;j<28-left[i];j++)
				c0[j]=c0[j+left[i]];
			for(j=28-left[i];j<28;j++)
				c0[j]=lleft[j+left[i]-28];

			for(j=0;j<left[i];j++)
				lleft[j]=d0[j];
			for(j=0;j<28-left[i];j++)
				d0[j]=d0[j+left[i]];
			for(j=28-left[i];j<28;j++)
				d0[j]=lleft[j+left[i]-28];

			//c0d0合起来56位
			for(j=0;j<28;j++)
				c0d0[j]=c0[j],c0d0[j+28]=d0[j];
			//将56位降为48位生成一个子密钥
			for(j=0;j<48;j++)
				keyk[i][j]=c0d0[key56to48[j]];
		}

		//经过16轮运算
		for(i=0;i<16;i++)
		{
			//l1=r0
			for(j=0;j<32;j++)
				l1[j]=r0[j];
			//r0 32位变成48位
			for(j=0;j<48;j++)
				r048[j]=r0[r32to48[j]];
			//分成8组,每组6bit,压缩至4bit
			for(group=0;group<8;group++)
			{
				k=0;
				for(everyGroup=0;everyGroup<6;everyGroup++)//每组6个,每位是r048^keyk[i]
					fb[everyGroup]=r048[group*6+everyGroup]^keyk[i][group*6+everyGroup];
				x=fb[0]*2+fb[5];
				y=fb[4]+fb[3]*2+fb[2]*4+fb[1]*8;
				r032[4*group]=(s[group][x*16+y]>>3)&1;
				r032[4*group+1]=(s[group][x*16+y]>>2)&1;
				r032[4*group+2]=(s[group][x*16+y]>>1)&1;
				r032[4*group+3]=s[group][x*16+y]&1;
			}
			//r1=l0^f(r0,ki)
			for(j=0;j<32;j++)
				r1[j]=l0[j]^r032[j];

			//此次的l1,r1变成下一次的l0,r0
			for(j=0;j<32;j++)
				l0[j]=l1[j],r0[j]=r1[j];
		}

		//16轮变换后,r16,l16组成新数
		for(i=0;i<32;i++)
		{
			after16[i]=r0[i];
			after16[i+32]=l0[i];
		}
		//然后再逆变换,得到密文
		for(i=0;i<64;i++)
			IP_1a[i]=after16[IP_1[i]];
		//比较得到的密文是否与B相同
		for(rB=0,i=63;i>=0;i--)
		{
			rB=(rB<<1)+IP_1a[i];
		}
		//如果相同,则输出结果
		if(rB==B)
		{
			flag=true;
			printf("(0,1206425)的密钥为%I64u\n",key);
			break;
		}
		else
		{
			printf("0经过密钥%I64u加密后的密文是:%I64u\n",KEY,rB);
		}
	}
	if(flag==false)
	{
		printf("\n随机生成了10000个密钥,密文都不是1206425。所以解密失败\n");
	}
	return 0;
}


 

详细过程参照这两篇博客

http://simplesource.blog.163.com/blog/static/103414062007221112947879/

http://blog.csdn.net/boksic/article/details/6896402