DES加密

DES

DES属于第一种对称加密技术
DES(数据加密标准)算法主要采用替换和移位的方式进行加密,
用56位(64位密钥只有56位有效)对64位二进制数据块进行加密,
每次加密对64位的输入数据进行16轮编码,
经过一系列替换和移位后,
输入的64位原数据转换成完全不同的64位输出数据。

流程图

每一轮运算
这里写图片描述

代码实现

des.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <bitset>
using namespace std;
typedef std::bitset<64> Block ;
typedef std::bitset<56> Key ;
typedef std::bitset<48> Code ;

typedef std::bitset<32> HBlock ;
typedef std::bitset<28> HKey ;
typedef std::bitset<24> HCode ;

typedef enum { e , d } Method ;

int ip(const Block & block , HBlock & left , HBlock & right) ;
int des_turn(HBlock & left , HBlock & right , const Code & subkey) ;
int exchange(HBlock & left , HBlock & right) ;
int rip(const HBlock & left , const HBlock & right , Block & block) ;
Code getkey(const unsigned int n , const Block & bkey) ;
int des(Block & block , Block & bkey , const Method method) ;

des.cpp

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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
#include "des.h"
//初始置换表
const static unsigned char ip_table[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
} ;

//扩展置换,将数据从32位扩展为48位
static const unsigned char expa_perm[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
} ;

//S盒子代替
const static unsigned char sbox[8][64]={
{//S1盒子
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
} ,
{//S2盒子
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
} ,
{//S3盒子
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
} ,
{//S4盒子
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
} ,
{//S5盒子
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
} ,
{//S6盒子
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
} ,
{//S7盒子
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
} ,
{//S8盒子
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盒置换
const static unsigned char p_table[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
} ;

//末置换
const static unsigned char ipr_table[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 ip(const Block & block , HBlock & left , HBlock & right)
{
for(size_t i = 0 ; i < right.size() ; ++i)
right[i] = block[ip_table[i] - 1] ;//获取置换后的右半部分
for(size_t i = 0 ; i < left.size() ; ++i)
left[i] = block[ip_table[i + left.size()] - 1] ;//获取置换后的左半部分
return 0 ;
}

//一轮加解密运算,不带交换
int des_turn(HBlock & left , HBlock & right , const Code & subkey)
{
Code code ;//48位数据块
HBlock pcode ;//32位数据块
//将右半部分扩展为48位
for(size_t i = 0 ; i < code.size() ; ++i)
code[i] = right[expa_perm[i] - 1] ;//扩展置换
code ^= subkey ;//与子密钥异或
//S盒代替
std::bitset<4> col ;//S盒的列
std::bitset<2> row ;//S盒的行
for(size_t i = 0 ; i < 8 ; ++i)
{//8个盒子
row[0] = code[6 * i] ;//获取行标
row[1] = code[6 * i + 5] ;
col[0] = code[6 * i + 1] ;//获取列标
col[1] = code[6 * i + 2] ;
col[2] = code[6 * i + 3] ;
col[4] = code[6 * i + 4] ;
std::bitset<4> temp(sbox[i][row.to_ulong() * 16 + col.to_ulong()]) ;
for(size_t j = 0 ; j < temp.size() ; ++j)
code[4 * i + j] = temp[j] ;//将32位暂存于48位中
}
for(size_t i = 0 ; i < pcode.size() ; ++i)
pcode[i] = code[p_table[i] - 1] ;//P盒置换
left ^= pcode ;//异或
return 0 ;
}

//交换左右两个部分
int exchange(HBlock & left , HBlock & right)
{
HBlock temp ;
for(size_t i = 0 ; i < temp.size() ; ++i)
temp[i] = left[i] ;
for(size_t i = 0 ; i < left.size() ; ++i)
left[i] = right[i] ;
for(size_t i = 0 ; i < right.size() ; ++i)
right[i] = temp[i] ;
return 0 ;
}

//将左右两部分数据进行末置换形成一个数据块
int rip(const HBlock & left , const HBlock & right , Block & block)
{
for(size_t i = 0 ; i < block.size() ; ++i)
{
if(ipr_table[i] <= 32)
block[i] = right[ipr_table[i] - 1] ;//从right部分获取数据
else
block[i] = left[ipr_table[i] - 32 - 1] ;//从left部分获取数据
}
return 0 ;
}

//密钥置换表,将64位密钥置换压缩置换为56位
const static unsigned char key_table[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
} ;

//每轮移动的位数
const static unsigned char bit_shift[16] = {
1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 1
} ;

//压缩置换表,56位密钥压缩位48位密钥
const static unsigned char comp_perm[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
} ;

//获取bkey产生的第n轮子密钥
Code getkey(const unsigned int n , const Block & bkey)
{//n在区间[0,15]之间取值,bkey为64位密钥
Code result ;//返回值,48位子密钥
Key key ;//56位密钥
unsigned int klen = key.size() , rlen = result.size() ;//分别为56和48
//获取56位密钥
for(size_t i = 0 ; i < key.size() ; ++i)
key[i] = bkey[key_table[i] - 1] ;//密钥置换
for(size_t i = 0 ; i <= n ; ++i)
{//循环移位
for(size_t j = 0 ; j < bit_shift[i] ; ++j)
{
//将密钥循环位暂存在result中
result[rlen - bit_shift[i] + j] = key[klen - bit_shift[i] + j] ;
result[rlen / 2 - bit_shift[i] + j] = key[klen / 2 - bit_shift[i] + j] ;
}
key <<= bit_shift[i] ;//移位
for(size_t j = 0 ; j < bit_shift[i] ; ++j)
{
//写回key中
key[klen / 2 + j] = result[rlen - bit_shift[i] + j] ;
key[j] = result[rlen / 2 - bit_shift[i] + j] ;
}
}
//压缩置换
for(size_t i = 0 ; i < result.size() ; ++i)
result[i] = key[comp_perm[i] - 1] ;
return result ;
}

//加解密运算
int des(Block & block , Block & bkey , const Method method)
{//block为数据块,bkey为64位密钥
HBlock left , right ;//左右部分
ip(block , left , right) ;//初始置换
switch(method)
{
case e://加密
for(char i = 0 ; i < 16 ; ++i)
{
Code key = getkey(i , bkey) ;
cout<<"秘钥"<<i+1<<": "<<key<<endl;
des_turn(left , right , key) ;
cout<<"密文"<<i+1<<": "<<left<<right<<endl;
if(i != 15) exchange(left , right) ;
}
break ;
case d://解密
for(char i = 15 ; i >= 0 ; --i)
{
Code key = getkey(i , bkey) ;
cout<<"秘钥"<<i+1<<": "<<key<<endl;
des_turn(left , right , key) ;
cout<<"密文"<<i+1<<": "<<left<<right<<endl;
if(i != 0) exchange(left , right) ;
}
break ;
default:
break ;
}
rip(left , right , block) ;//末置换
if (method==e)
cout<<"末置换以后,最终加密结果:\n"<<block<<endl;
else
cout<<"末置换以后,最终解密结果:\n"<<block<<endl;
return 0 ;
}

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
#include <cstdlib>
#include "des.h"

using namespace std ;

int main(){
Block data(0x5F205B66658C0000);
Block key(0x0123456789ABCDEF);
Method m=e;
cout<<"明文:\n"<<data<<"\n初始秘钥:\n"<<key<<endl;
cout<<"DES加密:\n";
des(data,key,m);
cout<<"\n\n密文:\n"<<data<<"\n初始秘钥:\n"<<key<<endl;
cout<<"DES解密:\n";
m = d;
des(data,key,m);
return 0;
}

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述