密码学课程设计-分组密码-DES

1 概述

数据加密标准(DES)的出现是现代密码发展史上的一个非常重要的事件,它是密码学历史上第一个广泛应用于商用数据保密的密码算法,并开创了公开密码算法的先例,极大地促进了密码学的发展。尽管在今天看来,它已经不足以保障数据安全,但是它曾成功地抵抗了几十年的分析攻击,且截至目前,其安全威胁主要来源于穷举攻击。换言之,如果使用诸如三重DES等方式来加长DES的秘钥长度,它仍不失为一个安全的密码系统。因此,DES算法的基本理论和设计思想仍有重要的参考价值。

2 算法原理与设计思路

DES的加密过程可分为置换、F函数和密钥编排三个部分,解密过程与此相似,这里仅介绍DES的加密过程。

2.1 置换分为初始置换和逆初始置换

初始置换和初始逆置换

2.2 F函数包含E盒扩展置换、密钥加、S盒代换和P盒置换

F函数

2.3 密钥编排

密钥编排

3 关键算法分析

main():函数作为函数的入口和出口
DESenc(mes, key):函数进行DES的加密入口
DESenc_test(mes, key):对一组明文进行加密
DESdec(cipher, key):函数进行DES的解密入口
DESdec_test(cipher, key):将密文直接输64位2进制
mov_IP(str):逆IP盒
funcF(str, key):F函数
box_p(str):P盒置换
box_s(str):S盒代换
box_e(str):e盒扩展
begin_change(str):初始置换
key_gen(str):密钥生成
key_change_2(str):pc-2置换
key_change_1(str):pc-1置换
xor(str1, str2):字符串异或
zuoyiwei(str,num):循环左移
strtobin(str):字符串转二进制

4 运行结果

完整代码如下所示:

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
# DES

# 字符串转二进制
def strtobin(str):
res = ""
for i in str:
tmp = bin(ord(i))[2:]
for i in range(0, 8 - len(tmp)):
tmp = '0' + tmp
res += tmp
return res

# 循环左移
def zuoyiwei(str,num):
my = str[num:len(str)]
my = my+str[0:num]
return my

# 字符串异或
def xor(str1, str2):
res = ""
for i in range(0, len(str1)):
xor_res = int(str1[i], 10)^int(str2[i], 10)
if xor_res == 1:
res += '1'
else:
res += '0'
return res

# PC-1盒处理
def key_change_1(str):
key1_list = [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]
res = ""
for i in key1_list:
res += str[i-1]
return res

# PC-2盒处理
def key_change_2(str):
key2_list = [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]
res = ""
for i in key2_list:
res += str[i-1]
return res

# 生成16个子密钥
def key_gen(str):
key_list = []
key_change_res = key_change_1(str)
key_c = key_change_res[0:28]
key_d = key_change_res[28:]
for i in range(1, 17): #共16轮
if (i == 1) or (i == 2) or (i == 9) or (i == 16):
key_c = zuoyiwei(key_c, 1)
key_d = zuoyiwei(key_d, 1)
else:
key_c = zuoyiwei(key_c, 2)
key_d = zuoyiwei(key_d, 2)
key_yiwei = key_c + key_d
key_res = key_change_2(key_yiwei)
key_list.append(key_res)
return key_list

# IP盒处理
def begin_change(str):
change_list = [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]
res = ""
for i in change_list:
res += str[i-1]
return res

# e盒处理
def box_e(str):
e_list = [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]
res = ""
for i in e_list:
res += str[i-1]
return res

# s盒处理
def box_s(str):
j = 0
s_list = [[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]
]
res = ""
for i in range(0, len(str), 6):
begin_s = str[i:i + 6]
row = int(begin_s[0] + begin_s[5], 2)
col = int(begin_s[1:5], 2)
num = bin(s_list[j][row * 16 + col])[2:]
for padd in range(0, 4 - len(num)):
num = "0" + num
res += num
j = j + 1
return res

# p盒处理
def box_p(str):
res = ""
p_list = [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]
for i in p_list:
res += str[i - 1]
return res

# F函数
def funcF(str, key):
str_e_res = box_e(str)
xor_res = xor(str_e_res, key)
str_s_res = box_s(xor_res)
str_p_res = box_p(str_s_res)
return str_p_res

# 逆IP盒
def mov_IP(str):
res = ""
ip_list = [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]
for i in ip_list:
res += str[i-1]
return res

# 针对一组的加密程序
def DESenc_test(mes, key):
mes_bin = strtobin(mes)
mes_IP = begin_change(mes_bin)
key_bin = strtobin(key)
key_list = key_gen(key_bin)
mes_left = mes_IP[0:32]
mes_right = mes_IP[32:]
for i in range(0, 15):
mes_tmp = mes_right
right_f_res = funcF(mes_right, key_list[i])
mes_right = xor(right_f_res, mes_left)
mes_left = mes_tmp
fin_right = mes_right
fin_left = xor(funcF(mes_right, key_list[15]), mes_left)
fin = fin_left + fin_right
fin = mov_IP(fin)
return fin

# 针对一组的解密程序
def DESdec_test(cipher, key): #密文直接输64位2进制
key_bin = strtobin(key)
key_list = key_gen(key_bin)
cipher = begin_change(cipher)
i = 15
cipher_left = cipher[0:32]
cipher_right = cipher[32:]
while i > 0:
cipher_tmp = cipher_right
cipher_right = xor(cipher_left, funcF(cipher_right, key_list[i]))
cipher_left = cipher_tmp
i = i - 1
fin_left = xor(cipher_left, funcF(cipher_right, key_list[0]))
fin_right = cipher_right
fin = fin_left + fin_right
fin = mov_IP(fin)
my_plain = ""
for j in range(0, len(fin), 8):
my_plain += chr(int(fin[j:j + 8], 2))
return my_plain

# DES加密
def DESenc(mes, key):
res = ""
i = 0
while mes[i:i+8] != "":
res += DESenc_test(mes[i:i+8], key)
i = i + 8
return res

# DES解密
def DESdec(cipher, key):
res = ""
i = 0
while cipher[i:i + 64] != "":
res += DESdec_test(cipher[i:i + 64], key)
i = i + 64
return res

def main():
plaintext = ''
key = ''
ciphertext = ''
userInput = ''
print("加密请按D,解密请按E:")
userInput = input()
if userInput == 'D':
print("请输入明文:")
plaintext = input()
print("请输入密钥:")
key = input()
ciphertext = DESenc(plaintext, key)
print("密文是:")
print(ciphertext)
else:
print("请输入密文:")
ciphertext = input()
print("请输入密钥:")
key = input()
plaintext = DESdec(ciphertext, key)
print("明文是:")
print(plaintext)

if __name__ == '__main__':
main()

运行效果如下图:

运行效果

5 密码安全性分析

5.1 对DES的S盒、迭代次数、密钥长度等设计准则的争议

5.2 DES存在一些弱密钥和半弱密钥

5.3 DES的56位密钥无法抵抗穷举攻击

5.4 代数结构存在互补对称性

密码安全性分析


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 xingshuaikun@163.com。

×

喜欢就点赞,疼爱就打赏