又是密码学作业,这次是一个三轮的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;
}