1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
#include <stdio.h>
#include <string.h>
#define DES_BLOCK_SIZE 8
#define KEY_SIZE 8
static const unsigned char DES_KEY[8] = {0x13, 0x34, 0x57, 0x79, 0x9B, 0xBC, 0xDF, 0xF1};
static const 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
};
static const int FP[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
};
static const 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
};
static const 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
};
static const 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
};
static const 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
};
static const int shifts[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1};
static const int S_BOX[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,10,15,6,8,0,5,9,14,2},{6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12}},
};
void permute(const unsigned char *in, unsigned char *out, const int *table, int size) {
memset(out, 0, (size+7)/8);
for(int i=0;i<size;i++){
int pos=table[i]-1;
int byte_idx=pos/8;
int bit_idx=7-(pos%8);
unsigned char bit=(in[byte_idx]>>bit_idx)&0x01;
out[i/8]|=(bit<<(7-(i%8)));
}
}
void left_shift(unsigned char *key,int shifts){
unsigned char temp=key[0]>>(8-shifts);
for(int i=0;i<3;i++) key[i]=(key[i]<<shifts)|(key[i+1]>>(8-shifts));
key[3]=(key[3]<<shifts)|temp;
}
void generate_subkeys(const unsigned char *key,unsigned char subkeys[16][6]){
unsigned char permuted_key[7]={0};
permute(key,permuted_key,PC1,56);
unsigned char C[4],D[4];
memcpy(C,permuted_key,4);
memcpy(D,permuted_key+3,4);
for(int i=0;i<16;i++){
left_shift(C,shifts[i]);
left_shift(D,shifts[i]);
unsigned char combined[7];
memcpy(combined,C,4);
memcpy(combined+3,D,4);
memset(subkeys[i],0,6);
permute(combined,subkeys[i],PC2,48);
}
}
void feistel(unsigned char *R,const unsigned char *subkey){
unsigned char expanded[6]={0};
permute(R,expanded,E,48);
for(int i=0;i<6;i++) expanded[i]^=subkey[i];
unsigned char output[4]={0};
for(int i=0;i<8;i++){
int idx=i*6;
int row=((expanded[idx/8]>>(7-(idx%8)))&0x01)<<1;
row|=(expanded[(idx+5)/8]>>(7-((idx+5)%8)))&0x01;
int col=0;
for(int j=1;j<=4;j++){
col<<=1;
col|=(expanded[(idx+j)/8]>>(7-((idx+j)%8)))&0x01;
}
int val=S_BOX[i][row][col];
output[i/2]|=(i%2==0)?(val<<4):val;
}
unsigned char temp[4]={0};
permute(output,temp,P,32);
memcpy(R,temp,4);
}
void des_crypt(const unsigned char *key,const unsigned char *input,unsigned char *output,int encrypt){
unsigned char subkeys[16][6];
generate_subkeys(key,subkeys);
unsigned char block[8]={0};
permute(input,block,IP,64);
unsigned char L[4],R[4];
memcpy(L,block,4);
memcpy(R,block+4,4);
for(int i=0;i<16;i++){
unsigned char temp[4];
memcpy(temp,R,4);
int idx = encrypt? i: 15-i;
feistel(R,subkeys[idx]);
for(int j=0;j<4;j++) R[j]^=L[j];
memcpy(L,temp,4);
}
unsigned char preoutput[8];
memcpy(preoutput,R,4);
memcpy(preoutput+4,L,4);
permute(preoutput,output,FP,64);
}
void des_encrypt(const unsigned char *key,const unsigned char *input,unsigned char *output){
des_crypt(key,input,output,1);
}
void des_decrypt(const unsigned char *key,const unsigned char *input,unsigned char *output){
des_crypt(key,input,output,0);
}
int main() {
const char *hex_ciphertext = "AEBCDE9B24029CA7";
unsigned char ciphertext[8] = {0};
unsigned char decrypted[8] = {0};
for (int i = 0; i < 8; i++) {
sscanf(hex_ciphertext + i * 2, "%2hhX", &ciphertext[i]);
}
des_decrypt(DES_KEY, ciphertext, decrypted);
printf("解密: %.8s\n", decrypted);
return 0;
}
|