C语言实现DES破解(3轮DES差分攻击)

又是密码学作业,这次是一个三轮的DES解密,废话少说,代码如下,每个函数和变量的作用注释的很清楚:
P.S.NUM 控制输入明密文对数目,(明文是经过IP置换之后的),如果同是密码学引论作业就不要看了,不是的话可以copy代码_

//2020/3/14 by小小小小梅 
#include<stdio.h>

#define NUM 5  //NUM表示输入的明文和密文对数

//PC1,负责去掉奇偶校验位,并且初步混乱
int PC1[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 };
//PC2,负责将密钥由56位变成48位 
int PC2[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 };

//S盒,负责将48位变回32位 
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,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 }
;

//p置换盒
int P[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 };
//E,负责将32位串扩散成48位 
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
};

//这里我们以如下明密文对进行示范
unsigned long long int plaintext[2*NUM] = {
	0x8066928BFAECD99D ,0xF9187686FAECD99D ,
	0xBCCB0915FB9DAD15 ,0X7C6A2463FB9DAD15 ,
	0X6EEF46EDDC4C3F51 ,0X5E9C57D2DC4C3F51 ,
	0XE682DAA5F83ECF3B ,0XD03F9B23F83ECF3B
};
unsigned long long int ciphertext[2*NUM] = {
	0X57DECC86A26EA1DC,0X699074ED42BBAA8A,
	0X1B1EF84FCAEE04DF,0XD82A8F73F24B36EC,
	0X9B4F437F1066BF01,0XEFB5FBC6AA1EDEF9,
	0X2811CBA30B25F712,0X1544A0610224698A
};
//控制密钥的循环移位
int move_bit[3] = {1,2,4};
//这里显示的是IP置换后,我们要穷举的数位
int loss_bit[8] = { 0, 12, 21, 25, 38, 41, 46, 29 };
//转换为2进制的两部分32位的明密文
int plaintext_2[2 * NUM][2][32];
int ciphertext_2[2 * NUM][2][32];
int choice[64][6] = {0}; //这个是所有可能的输入值
int key_count[8][64] = {0 };//此函数用于计数当s盒的输入异或输出异或固定的条件下,满足的R2数目
int key_8[8];
int key_48[48];
int key_56[56] = { 0 };
int f_key_56[56];
int s_out[NUM][32], s_in[NUM][48];
int KEY[64] = {0};
int KEY_8[8] = { 0 };
void change_2();//此函数将16进制输入输出转换为8进制
void xor_operation(int result[], int a[], int b[], int num); //此函数做异或操作
void E_operation(int E_R2[2 * NUM][48]);    //进行E操作
void Find_8_key(int k, int E_R2[2 * NUM][48]);  //寻找第3轮密钥
void make_key(int i, int key[48]);    //由原始密钥产生轮密钥 
void F_Operation(int RC[32], int key[]);   //F函数,包括E扩散,异或,S盒,P操作 
int DES();  //进行DES加密操作
int Exhaustion();  //穷举法得到真实56位密钥


int main()
{
	int E_R2[2 * NUM][48];
	int R3_xor[NUM][32], L0_xor[NUM][32], R_L_xor[NUM][32];
	change_2();
	E_operation(E_R2);
	/*计算出五组的  R3^R3*  和  L0^L0* 并将他们存储在R3_xor[5][32]和L0_xor[5][32]
	计算出c^c*=R3^R3*^L0^L0*,并且存储在s盒的输出异或中*/
	for (int num = 0; num < NUM; num++)
	{
		xor_operation(R3_xor[num], ciphertext_2[2 * num][1], ciphertext_2[2 * num + 1][1], 32);
		xor_operation(L0_xor[num], plaintext_2[2 * num][0], plaintext_2[2 * num + 1][0], 32);
		xor_operation(R_L_xor[num], R3_xor[num], L0_xor[num], 32);
		xor_operation(s_in[num], E_R2[2 * num], E_R2[2 * num + 1], 48);
		for (int i = 0; i < 32; i++)
			s_out[num][P[i] - 1] = R_L_xor[num][i];
	}
	//寻找到K3
	for (int k = 0; k < 8; k++)
		Find_8_key(k, E_R2);
	printf("第3轮轮密钥是:");
	for (int i = 0; i < 8; i++)
		printf("%d   ", key_8[i]);
	//转换为PC1置换的56位密钥
	for (int i = 0; i < 8; i++)
		for (int j = 0; j < 6; j++)
			key_48[6 * i + j] = key_8[i] >> (5 - j) & 1;
	for (int i = 0; i < 48; i++)
		printf("%d",key_48[i]);
	for (int i = 0; i < 48; i++)
		key_56[PC2[i] - 1] = key_48[i];
	for (int i = 0; i < 56; i++)
	{
		if (i < 28)
			f_key_56[i] = key_56[(i + 24) % 28];
		else
			f_key_56[i] = key_56[28 + ((i + 24) % 28)];
	}
	int tag = Exhaustion();
	if (tag == 1)
		printf("成功了^_^!\n");
	else
		printf("失败了^_^!\n");

	for (int i = 0; i < 56; i++)
		KEY[PC1[i]-1] = f_key_56[i];
	int bit_8 = 0;
	printf("原密钥是:");
	for (int i = 0; i < 8; i++)
	{
		for (int j = 0; j < 7; j++)
		{
			if (KEY[8 * i + j] == 0)
				bit_8++;
			KEY_8[i] += KEY[8 * i + j] << (7 - j);
		}
		if (bit_8 % 2 == 0)
			KEY[8 * i + 7] = 0;
		else
			KEY[8 * i + 7] = 1;
		bit_8 = 0;
		KEY_8[i] += KEY[8 * i + 7];
		printf("%X", KEY_8[i]);
	}
}

void change_2()
{
	for (int i = 0; i < 2 * NUM; i++)
		for (int j = 0; j < 64; j++)
		{
			if (j<32)
			{
				plaintext_2[i][1][31 - j] = plaintext[i] >> j & 1;
				ciphertext_2[i][1][31 - j] = ciphertext[i] >> j & 1;
			}
			else
			{
				plaintext_2[i][0][63 - j] = plaintext[i] >> j & 1;
				ciphertext_2[i][0][63 - j] = ciphertext[i] >> j & 1;
			}
		}
}

void xor_operation(int result[], int a[], int b[],int num)
{
	for (int i = 0; i < num; i++)
		result[i] = a[i] ^ b[i];
}

void E_operation(int E_R2[2 * NUM][48])
{
	for (int num=0;num< 2 * NUM;num++)
		for (int i = 0; i < 48; i++)
			E_R2[num][i] = ciphertext_2[num][0][E[i] - 1];
}
void Find_8_key(int k, int E_R2[2 * NUM][48])   //num代表处理的第几对数据,k代表处理数据的第几个6字符组
{
	int temp[6];
	int a, b,c,d=0;
	for (int num = 0; num < NUM; num++)
	{
		for (int i = 0; i < 64; i++)
		{
			for (int j = 0; j < 6; j++)
			{
				choice[i][5 - j] = (i >> j) & 1;
				//printf("%d",choice[i][5-j]);//将choice遍历所有的0-63的二进制
			}
			for (int j = 0; j < 6; j++)
			{
				temp[j] = choice[i][j] ^ s_in[num][6 * k + j];//得到E处理后的一组数
				//printf("%d", temp[j]);
			}
			//获得输出异或
			a = S[k][(temp[0] << 1) + temp[5]][(temp[1] << 3) + (temp[2] << 2) + (temp[3] << 1) + temp[4]];
			b = S[k][(choice[i][0] << 1) + choice[i][5]][(choice[i][1] << 3) + (choice[i][2] << 2) + (choice[i][3] << 1) + choice[i][4]];
			c = (s_out[num][4 * k] << 3) + (s_out[num][4 * k + 1] << 2) + (s_out[num][4 * k + 2] << 1) + s_out[num][4 * k + 3];
			if ((a ^ b) == c)//当s盒输出的异或和s_out相等时
			{
				for(int q=0;q<6;q++)
				d+=E_R2[2*num][6*k+q]<<(5-q);
			    d = d ^ i;       //获得对应的子密钥
				//printf("  %d %d %d %d\n",d ,a, b, c);
				key_count[k][d]++;
				d = 0;
			}
		}
	}
	printf("第%d组数\n", k+1);
	for (int i = 0; i < 64; i++)
		printf("%d ", key_count[k][i]);
	printf("\n");
	for (int i = 0; i < 64; i++)
		if (key_count[k][i] == NUM)  //当被选中的和对数相同时,即为轮密钥
			key_8[k] = i;
}
int DES()
{
	int L[32], R[32];
	for (int i = 0; i < 32; i++)
	{
		L[i] = plaintext_2[0][0][i];
		R[i] = plaintext_2[0][1][i];
	}
	int key[48], temp[32];
	for (int i = 1; i <= 3; i++)
	{
		for (int j = 0; j < 32; j++)
		{
			temp[j] = L[j];
			L[j] = R[j];
		}
		make_key(i, key);   //生成子密钥
		F_Operation(R, key);   //进行f处理
		for (int j = 0; j < 32; j++)    //R(i)=L(i-1)^F()
			R[j] = R[j] ^ temp[j];
	}
	for (int i = 0; i < 32; i++)
		if (L[i] == ciphertext_2[0][0][i] && R[i] != ciphertext_2[0][1][i])
			return 0;
	return 1;  //当1的时候才成功
}

void make_key(int i, int key[48])
{
	int key1[28] = { 0 }, key2[28] = {0};
		for (int index = 0; index < 28; index++)
		{
			key1[index] = f_key_56[(index + move_bit[i - 1]) % 28];
			key2[index] = f_key_56[28+((index + move_bit[i - 1]) % 28)];
		}
	for (int i = 0; i < 48; i++)
	{
		if (PC2[i] <= 28)
			key[i] = key1[PC2[i] - 1];
		if (PC2[i] > 28)
			key[i] = key2[PC2[i] - 29];
	}
}

void F_Operation(int R[32], int key[])   //F()
{
	int x, y;
	int TR[32];
	int TRC[48], TRCO[48];
	for (int i = 0; i < 48; i++)
	{
		TRC[i] = R[E[i] - 1];
		TRCO[i] = TRC[i] ^ key[i];
	}
	for (int j = 0; j < 8; j++)
	{
		x = (TRCO[j * 6] << 1) + TRCO[j * 6 + 5];
		y = (TRCO[j * 6 + 1] << 3) + (TRCO[j * 6 + 2] << 2) + (TRCO[j * 6 + 3] << 1) + TRCO[j * 6 + 4];
		for (int k = 0; k < 4; k++)
		{
			TR[j * 4 + k] = S[j][x][y] >> (3 - k) & 1;
		}
	}
	for (int i = 0; i < 32; i++)
	{
		R[i] = TR[P[i] - 1];
	}
}

int Exhaustion()
{
	printf("\n");
	int loss_bit[8] = { 0, 12, 21, 25, 38, 41, 46, 29 };
	int i = 0;
	for(f_key_56[0 ]=0; f_key_56[0]<2; f_key_56[0]++)
		for (f_key_56[12] = 0; f_key_56[12] < 2; f_key_56[12]++)
			for (f_key_56[21] = 0; f_key_56[21] < 2; f_key_56[21]++)
				for (f_key_56[25] = 0; f_key_56[25] < 2; f_key_56[25]++)
						for (f_key_56[38] = 0; f_key_56[38] < 2; f_key_56[38]++)
							for (f_key_56[41] = 0; f_key_56[41] < 2; f_key_56[41]++)
								for (f_key_56[46] = 0; f_key_56[46] < 2; f_key_56[46]++)
									for (f_key_56[29] = 0; f_key_56[29] < 2; f_key_56[29]++)
									{
										if (DES() == 1)
											return 1;
									}
	return 0;
}
  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值