des加密详解

des学习

Feistel cipher

首先我们得了解一下什么是feistel加密 feistel加密是一种区块加密 一张图解释完毕~ blacsheep 需要注意的是,feistel是一种加密的框架,因为其中的f可以由用户自行定义,而且f对于解密不产生任何影响。提醒一点:解密的时候首先要把L和R反一下,一开始写des的时候解密就是因为最后没有注意到这里导致无法解密,最后手撸des的时候发现这一点才解决...

des加密

简单的了解了feistel之后我们就开始了解一下des咯 Data Encryption Standard缩写des 个人理解,des加密主要分为三个部分:

一个部分是IP和IP-1置换

blacsheep 也就是原来的第58位放到第一位,第50位放到第二位balabala..

一个部分是密钥的处理

blacsheep 16轮迭代之后恰好为28,回到原点继续代下一个块

一个是feistel中f的实现

首先总体的框架 blacsheep 具体看下每个部分

E盒

32bits->48bits blacsheep

S盒

blacsheep 具体的使用,举个栗子,假设第一个6bits为110101,取首位两个bits,即为11,为3对应第三行 中间1010为10对应第十列,第一个6bits对应S1那么就换成12,即1100 也就通过S盒完成了110101->1100的6bits到4bits的转换 列出8个S盒: S盒1: 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 S盒2: 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 S盒3: 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 S盒4: 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 S盒5: 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 S盒6: 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 S盒7: 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 S盒8: 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盒

S盒输出的32位继续按照P盒进行置换。 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 比如原来的第21为放到第4位,替换完成就完成了f的最后操作

给个代码

只写了bits的部分和bin2asc,asc2bin的函数,因为des的padding不清楚...等研究研究再改...

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
def padding(src,num):
src = str(src)
src = '0'*(num-len(src))+src
return src

def xor(str1,str2):
res = []
for i in range(len(str1)):
if int(str1[i])==int(str2[i]):
res.append(0)
else:
res.append(1)

return res

def list_from_zero(list1):
new = []
for each in list1:
new.append(each-1)
return new

def bin2asc(list_of_bin):
group = [list_of_bin[8*i:8*i+8] for i in range(int(len(list_of_bin)/8))]
res = ''
for one in group:
temp = 0
for each in one:
temp*=2
temp+=int(each)
res+=chr(temp)
return res

def asc2bin(str1):
res = ''
for each in str1:
res+=padding(bin(ord(each))[2:],8)
return res


class DES:
def __init__(self,key):
self.key=''
key=key[0:8]
print("[*]key只取了8个字母扩展成bits,长于8个字母的key取了前八个字母!")
for i in key:
self.key+=padding(bin(ord(i))[2:],8)

self.p_box_left = list_from_zero([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])
self.p_box_right = list_from_zero([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])


self.key_left = [self.key[i] for i in self.p_box_left]
self.key_right = [self.key[i] for i in self.p_box_right]

self.s=[[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]]

self.p = list_from_zero([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])

self.p_rev = list_from_zero([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])

self.roll_dict = {1:1,2:1,3:2,4:2,5:2,6:2,7:2,8:2,9:1,10:2,11:2,12:2,13:2,14:2,15:2,16:1}


self.yasuo = list_from_zero([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])

self.p_box = list_from_zero([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])

def IP_change(self,plain):
new_plain = [plain[i] for i in self.p]
return new_plain

def IP_rev(self,cypher):
new_cypher = [cypher[i] for i in self.p_rev]
return new_cypher

def key_gen(self,times):
roll_time = self.roll_dict[times]
for i in range(roll_time):
temp = self.key_left.pop(0)
self.key_left.append(temp)

temp = self.key_right.pop(0)
self.key_right.append(temp)

all_list = self.key_left+self.key_right
final = [all_list[i] for i in self.yasuo]
return final

def key_gen_decode(self,times):
roll_time = self.roll_dict[17-times]

all_list = self.key_left+self.key_right
final = [all_list[i] for i in self.yasuo]

for i in range(roll_time):
temp = self.key_left.pop(-1)
self.key_left.insert(0,temp)

temp = self.key_right.pop(-1)
self.key_right.insert(0,temp)



return final

def E_box(self,part):
first_list = [part[i*4:i*4+4] for i in range(8)]
second_list = []
for each in range(len(first_list)):
temp = first_list[each][:]
temp.insert(0,first_list[(each-1)%8][-1])
temp.append(first_list[(each+1)%8][0])
second_list += temp

return second_list

def S_box(self,part):
group = [part[6*i:6*i+6] for i in range(8)]
final = []
i=0
for each in group:
row = each[0]*2+each[5]
col = each[4]+each[3]*2+each[2]*4+each[1]*8
temp = padding(bin(self.s[i][row*16+col])[2:],4)
i+=1
for one in temp:
final.append(int(one))
return final

def P_box(self,part):
final = [part[i] for i in self.p_box]
return final


def decode_64bits(self,plain):
ipchange = self.IP_change(plain)
L = ipchange[0:32]
R = ipchange[32:]

for i in range(16):
extend = self.E_box(L[:])
key = self.key_gen_decode(i+1)
after_xor = xor(extend,key)
after_s = self.S_box(after_xor)
after_p = self.P_box(after_s)
final = xor(R,after_p)
R=L[:]
L = final[:]



res = ''.join([str(i) for i in self.IP_rev(L+R)])
return res

def encode_64bits(self,cypher):
ipchange = self.IP_change(cypher)
L = ipchange[0:32]
R = ipchange[32:]

for i in range(16):
temp = L[:]
L = R[:]
extend = self.E_box(R)
key = self.key_gen(i+1)
after_xor = xor(extend,key)
after_s = self.S_box(after_xor)
after_p = self.P_box(after_s)
final = xor(temp,after_p)
R = final[:]



res = ''.join([str(i) for i in self.IP_rev(L+R)])
return res


def analyse():
a=DES('DeS_KeY!')
str1='1000100101000100001101001000101110000101000000010001011100110000'
# print(a.decode_64bits('1'*64))
# 1000100101000100001101001000101110000101000000010001011100110000
for each in range(len(str1)):
new = list(str1[:])
if new[each]=='1':
new[each]='0'
new=''.join(new)
res = a.decode_64bits(new)
print("第"+str(each+1)+"位明文改变了密文的:第",end='')
for sec in range(len(res)):
if res[sec]=='0':
print(str(sec+1),end=' ')
print("改变")
print()

else:
new[each]='1'
new=''.join(new)
res = a.decode_64bits(new)
print("第"+str(each+1)+"位明文改变了密文的:第",end='')
for sec in range(len(res)):
if res[sec]=='0':
print(str(sec+1),end=' ')
print("改变")
print()





if __name__=="__main__":
#analyse()
a=DES('DeS_KeY!')
print("plain:",'1101'*16)
temp = a.encode_64bits('1101'*16)
print("cypher:",temp)
print("decode",a.decode_64bits(temp))

#plain: 1101110111011101110111011101110111011101110111011101110111011101
#cypher: 0000001010110100101011010011011001100010110001101100000010101011
#decode 1101110111011101110111011101110111011101110111011101110111011101