Sky's blog

密码学课程设计二之手撸DES加解密程序

字数统计: 1,991阅读时长: 11 min
2017/12/24 Share

前记

因为手撸的目的是了解DES加解密全过程,所以并没有追求效率,当时写的时候也很快就写完了,后面如果有时间会改进效率,毕竟测试了一下……加密7000单词的作文需要2秒……实在是太差了,毕竟菜鸡= =

简单说一下原理

密钥编排

1.首先输入64bit密钥
2.将64bit密钥经过PC-1盒变成56bit
3.将56bit分为C0和D0,分别28bit
4.将C0,D0分别循环移位,得到C1,D1
5.将C1,D1拼接,经过PC-2盒变成48bit子密钥key1
6.重复步骤4
7.生成16组子密钥
这里真实加密只用到56bit,后面会有文章借助一道DES题目细致讲解这个密钥编排

F函数

1.将输入的32bit的R经过E盒生成48bit
2.将该48bit值与子密钥异或
3.将异或后的值经过S盒置换,又变回32bit
4.将值经过P盒置换
5.将32bit值与L进行异或得到下一个R

加密程序

1.输入64bit明文
2.经过IP盒置换打乱生成str
3.将str分为L0和R0,分别32bit
4.以下重复15次:
5.将Ri经过F函数处理,再与Li异或,然后将值赋给R(i+1)
6.将Ri赋值给L(i+1)
7.最后一轮,直接将Ri赋给R(i+1),再将Ri经过F函数处理,再与Li异或,然后将值赋给L(i+1)
8.将L和R合并后经过逆IP盒,得到密文C

解密程序

加密程序的逆,就不赘述了,直接看下面的代码吧

DES加解密程序各个函数

字符串转二进制

1
2
3
4
5
6
7
8
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

循环左移

1
2
3
4
def zuoyiwei(str,num):
my = str[num:len(str)]
my = my+str[0:num]
return my

字符串异或

1
2
3
4
5
6
7
8
9
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盒处理

1
2
3
4
5
6
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盒处理

1
2
3
4
5
6
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个子密钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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盒处理

1
2
3
4
5
6
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] #因为列表是1-64,而数组是0-63,所以减一
return res

e盒处理

1
2
3
4
5
6
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盒处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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盒处理

1
2
3
4
5
6
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函数

就是上面e盒,异或,s盒,p盒的调用

1
2
3
4
5
6
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盒

1
2
3
4
5
6
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

针对一组的加密程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

针对一组的解密程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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加密

1
2
3
4
5
6
7
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解密

1
2
3
4
5
6
7
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
点击赞赏二维码,您的支持将鼓励我继续创作!
CATALOG
  1. 1. 前记
  2. 2. 简单说一下原理
    1. 2.1. 密钥编排
    2. 2.2. F函数
    3. 2.3. 加密程序
    4. 2.4. 解密程序
  3. 3. DES加解密程序各个函数
    1. 3.1. 字符串转二进制
    2. 3.2. 循环左移
    3. 3.3. 字符串异或
    4. 3.4. PC-1盒处理
    5. 3.5. PC-2盒处理
    6. 3.6. 生成16个子密钥
    7. 3.7. IP盒处理
    8. 3.8. e盒处理
    9. 3.9. s盒处理
    10. 3.10. p盒处理
    11. 3.11. F函数
    12. 3.12. 逆IP盒
    13. 3.13. 针对一组的加密程序
    14. 3.14. 针对一组的解密程序
    15. 3.15. DES加密
    16. 3.16. DES解密