DES算法简单介绍
DES是一种分组密码。明文、密文和密钥的分组长度都是64位;
DES是面向二进制的密码算法,因而能够加解密任何形式的计算机数据;
DES是对合运算,因而加解密共用同一个算法,从而使工程实现的工作量减半;
DES的密码结构属于Feistel结构,这种结构是IBM的密码专家Feistel最早提出的。
DES算法的细节网上有很多,因此不详细展开。
代码结构主要包括:
- 子密钥的产生:置换选择1,循环左移,置换选择2;
- 初始置换IP;
- 加密函数f:选择运算E,代替函数组S(也就是S盒处理),置换运算;
- 逆初始置换IP;
- DES最后加解密。
没有规范学习过python,代码风格可能不太好,直接硬写,对于代码风格以及实现过程若有错误或者建议,恳请指出。
tkinter效果
实现代码
DES.py
# -*- coding: utf-8 -*-
# DES.py
#生成子密钥
#64位密钥经过置换选择1、循环左移、置换选择2等变换,产生16个48位长的子密钥
#参数是64位密钥
def generkey(key):
keylist = list(key)#将输入密钥转换为列表
#置换选择1
left = [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]
right = [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] #28位
C0 = []
D0 = []
for i in range(len(left)):
a = left[i]
b = right[i]
C0.append(keylist[a-1])
D0.append(keylist[b-1])
C = [] #C=[C0,C1,C2...C16]
D = []
C.append(C0)
D.append(D0)
K = []
Movetime = [1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1]
for i in range(16):
a = Movetime[i]#循环左移的位数
l = C[i]
l = l[a:]+l[:a]#循环左移,得到下一个Ci
C.append(l)
r = D[i]
r = r[a:]+r[:a]
D.append(r)
inter_result= C[i+1] + D[i+1] # Ci+Di,并成56位的中间数据
K.append(inter_result)
#置换选择2,选出16个48位的子密钥Ki
Result = [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]
for i in range(16):
a = K[i]
d = []
for j in range(48):
c = Result[j] #第一轮
b = a[c-1] #b=a[13]
d.append(b) #子密钥的第一位是中间数据的第14位
K[i] = d #生成的子密钥
return K
#初始置换IP
#将64位明文打乱成重排,并分成左右两半,左边32位作为L0,右边32位为R0
#参数是64位明文
def chushizhihuan(mingwen):
Minglist = list(mingwen)
zhihuan_matrix = [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]
L0 = []
R0 = []
for i in range(32):
l = zhihuan_matrix[i] #l = 58,=Minglist[58]第58位
L = Minglist[l-1]
L0.append(L)
r = zhihuan_matrix[i+32]
R = Minglist[r-1]
R0.append(R)
M=[0,0]
M[0]=L0
M[1]=R0
return M #返回置换之后的明文
#加密函数f
#在第i次加密迭代中用密钥Ki对Ri-1进行加密
#参数Ri是32位输入A,k是48位子密钥
def f_func(Ri,k):
#选择运算,对32为数据组A进行选择和排列,产生48位结果
A = list(Ri) #a=32位
E = [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]
b = []
for i in range(48):
c = E[i] #第一轮,c=32
d = A[c-1] #48位中间结果的第一位是A的第32位
b.append(d) #b即48位的中间结果
#中间结果与子密钥异或运算
for i in range(48):
b[i] = int(b[i]) ^ int(k[i])
#盒子S运算
s = [0, 0, 0, 0, 0, 0, 0, 0]
#将异或结果分成8组,每组6位
for i in range(8):
s[i] = b[i * 6:(i + 1) * 6]
S=[0,0,0,0,0,0,0,0]
#8个S盒
S[0] = [[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[1] = [[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[2] = [[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[3]= [[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[4] = [[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[5] = [[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[6] = [[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[7] = [[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]]
#输入s
s2 = []
for i in range(8):
row = s[i][0] * 2 + s[i][5]#第1位和第6位代表选中的行号
col = s[i][1]*8+s[i][2]*4+s[i][3]*2+s[i][4]#其余4位代表选中的列号
s1=S[i][row][col]#
s1='{:04b}'.format(s1)#将选中的数转换成4位二进制字符串
s1 = list(s1)
s2 = s2 + s1
d = zhihuanyunsuan(s2)
return d
#置换运算P
#把S盒输出的32位数据打乱重排,得到32位的加密函数输出
#输入参数是S盒输出的32位数据
def zhihuanyunsuan(s2):
a = s2
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]
d = []
for i in range(32):
b = P[i]#b=16
c = a[b-1]
d.append(c)
return d
#是初始置换IP的逆置换,它把64位加密迭代的结果打乱重排,形成64位密文
#输入参数是最后一轮的R,L
def nizhuanhuan_IP(R16,L16):
IP = R16+L16
c = []
ip = [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 range(64):
a = ip[i]#a=40
b = IP[a-1]
c.append(b)
list1 = [str(i) for i in c]
list2 = ''.join(list1)
return list2
#flag为1时是解密,0是加密
#参数mingwen是明文或者密文,key是密钥
def DES(flag,mingwen,key):
Key = generkey(key)#生成密钥
M = chushizhihuan(mingwen)
L0 = M[0]
R0 = M[1]
R = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [],[]]
R[0] = R0
L = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [],[]]
L[0] = L0
d = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
for j in range(16):
if flag == "0":
d[j]=f_func(R[j],Key[j])
else:
#解密时使用子密钥的顺序正好反过来
d[j] = f_func(R[j], Key[15-j])
for i in range(32):
qin = int(d[j][i])^int(L[j][i])
R[j+1].append(qin)
L[j+1] = R[j]
list2 = nizhuanhuan_IP(R[16],L[16])
return list2
#key 0011000100110010001100110011010000110101001101100011011100111000
#明文 0011000000110001001100100011001100110100001101010011011000110111
#密文 1000101110110100011110100000110011110000101010010110001001101101
#DES.DES("0","0011000000110001001100100011001100110100001101010011011000110111","0011000100110010001100110011010000110101001101100011011100111000")
#DES.DES("1","1000101110110100011110100000110011110000101010010110001001101101","0011000100110010001100110011010000110101001101100011011100111000")
tkinter_1.py,实现简单图像化界面
# -*- coding: utf-8 -*-
import DES
import tkinter as tk # 使用Tkinter前需要先导入
# 第1步,实例化object,建立窗口window
window = tk.Tk()
window.title('DES 工具')
window.geometry('800x160')
l = tk.Label(window, text='明文/密文:', font=('Arial', 12), width=11, height=1)
r = tk.Label(window, text='密钥:', font=('Arial', 12), width=15, height=1)
t = tk.Label(window, text='结果:',font=('Arial', 12), width=15, height=1)
l.pack(anchor='w',ipady=20)
r.pack(anchor='w',pady=5)
t.pack(anchor='w',pady=15)
ming_or_mi = tk.StringVar()
entry_ming_or_mi = tk.Entry(window, textvariable=ming_or_mi, font=('Arial', 13),width=65)
entry_ming_or_mi.place(x=100,y=20)
key = tk.StringVar()
entry_key = tk.Entry(window, textvariable=key, font=('Arial', 13),width=65)
entry_key.place(x=100,y=70)
result = tk.Text(window,font=('Arial', 12),width=65,height=1.4)
result.place(x=100,y=116)
#加密
def Encrypt():
mingwen = ming_or_mi.get()
Key = key.get()
list2 = DES.DES("0",mingwen, Key)
str2 = "".join(list2)
result.delete(1.0, "end")#结果输入前先将输出框清空
result.insert(1.0,str2)
#解密
def Decrypt():
miwen = ming_or_mi.get()
Key = key.get()
list2 = DES.DES("1",miwen, Key)
str2 = "".join(list2)
result.delete(1.0, "end")#结果输入前先将输出框清空
result.insert(1.0, str2)
btn_jiami = tk.Button(window, text='加 密',font=('Arial', 10),width=5,command=Encrypt)
btn_jiami.place(x=720, y=17)
btn_jiemi = tk.Button(window, text='解 密',font=('Arial', 10),width=5,command=Decrypt)
btn_jiemi.place(x=720, y=65)
window.mainloop()
来源:CSDN
作者:QYQ 323
链接:https://blog.csdn.net/qq_43710705/article/details/103810799