DES算法将明文分成64位大小的众多数据块,即分组长度为64位。同时用56位密钥对64位明文信息加密,最终形成64位的密文。如果明文长度不足64位,则将其扩展为64位(如补零等方法)。具体加密过程首先是将输入的数据进行初始换位(IP),即将明文M中数据的排列顺序按一定的规则重新排列,生成新的数据序列,以打乱原来的次序。然后将变换后的数据平分成左右两部分,左边记为L0,右边记为R0,然后对R0实行在子密钥(由加密密钥产生)控制下的变换f,结果记为f(R0,K1),再与L0做逐位异或运算,其结果记为R1,R0则作为下一轮的L1。如此循环16轮,最后得到L16、R16,再对L16、R16实行逆初始置换IP-1,即可得到加密数据。解密过程与此类似,不同之处仅在于子密钥的使用顺序正好相反。
DES加解密过程:
f函数处理流程:
子密钥产生流程:
python源代码:
'''
args = {
name:DES加解密
author:Lsy
date:2020-11-18
}
'''
#关于需要对数据处理的相关表格
#初始置换IP
IP_table = [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
]
#逆初始置换IP表
IP_Inverse_table = [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
]
#选择扩展运算E(将32位扩展为48位)
E_table = [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
]
# 置换运算P表
P_table = [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
]
# S盒
S_box = [
# 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],
]
# 关于对秘钥处理的相关表格
# 置换选择表1,对秘钥进行压缩,将64位压缩成56位
PC1_table = [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
]
# 置换选择表2,对秘钥进行压缩,将56位压缩成48位
PC2_table = [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
]
# 循环移位位数表
left_rotations = [1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1]
#字符串转换成二进制bit串
def StringToBit(string,mode=1):
'''
args = {
string:需要转换的字符串
mode:转换模式,如果为1,则使用十六进制;如果为2,则使用unicode编码,16位,可加密中文;如果为3,使用unicode编码,8位
返回值:
Bit:二进制bit列表,形如[[01010.....][0020102....]],其中每个列表中有64位
}
'''
Bit = []
j = 1
str1 = ''
if mode==1:#十六进制模式
for i in range(len(string)):
n = int(string[i], 16)
a = []
for j in range(4):
a.insert(0, str(n % 2))
n = int(n / 2)
str1 = str1+''.join(a)
if i % 16 == 15:
Bit.append(list(int(m) for m in str1))
str1 = ''
if len(string) % 16 != 0:
str1 = str1.ljust(64, '0')
Bit.append(list(int(m) for m in str1))
return Bit
elif mode==2:#unicode16位模式
bitnum = 16
else:#unicode8位模式
bitnum = 8
for i in string:
str1+="{0:b}".format(ord(i)).zfill(bitnum)
if j%(64/bitnum)==0:
Bit.append(list(int(m) for m in str1))
str1 = ''
j +=1
if len(string)%(64/bitnum)!=0:
str1 = str1.ljust(64,'0')
Bit.append(list(int(m) for m in str1))
return Bit
#将bit换成字符串
def BitToString(Bit,mode=1):
'''
args = {
Bit:需要转换的二进制字符串,形如:如[[01010.....][0020102....]],其中每个列表中有64位
mode:转换模式,如果为1,则使用十六进制;如果为2,则使用unicode编码,16位,可加密中文;如果为3,使用unicode编码,8位
返回值:
Bit:二进制bit列表,形如[['0','1','0'.....]['0','0','0'....]],其中每个列表中有64位
}
'''
String = ''
if mode == 1:
for i in Bit:
for j in range(16):
String += hex(
i[4 * j] * 8 + i[4 * j + 1] * 4 + i[4 * j + 2] * 2 + i[4 * j + 3] * 1)[
2:].upper()
return String
elif mode==2:
bitnum = 16
else:
bitnum = 8
for i in Bit:
for j in range(int(64/bitnum)):
str1 = i[j*bitnum:(j+1)*bitnum]
str2 = ''
for z in str1:
str2 += str(z)
String += chr(int(str2,2))
return String
#辅助函数
def bitTTToString(i,n):
'''
args = {
i:带有n为bit字符串的列表
n:位数
返回十六进制字符串
}
'''
String = ''
for j in range(n):
String += hex(
i[4 * j] * 8 + i[4 * j + 1] * 4 + i[4 * j + 2] * 2 + i[4 * j + 3] * 1)[
2:].upper()
return String
#F函数
def F_function(R,K):
'''
args = {
R:右半部分,二进制串列表,32位
K:经过置换选择2的密钥二进制串列表,48位
返回值:
R:经过F函数加工后的二进制串列表,右半部分,32位
}
'''
extend = []
for i in range(48):#扩展置换(E表)
extend.append(R[E_table[i]-1])
R.clear()
for i in range(48):#扩展后的列表与密钥列表异或
R.append(extend[i]^K[i])
extend.clear()
for i in range(8):#S盒变换
row = R[i*6]*2 + R[i*6+5]
col = R[i*6+1]*8 + R[i*6+2]*4 + R[i*6+3]*2 + R[i*6+4]
num = S_box[i][16*row+col]
str = "{0:b}".format(num).zfill(4)
extend.extend(int(m) for m in str)
R.clear()
for i in range(32):#P表置换
R.append(extend[P_table[i]-1])
return R
#将秘钥压缩成56位
def miyao1(keystring,mode=1):
'''
args = {
keystring:密钥字符串
mode:转换模式,如果为1,则使用十六进制;如果为2,则使用unicode编码,16位,可加密中文;如果为3,使用unicode编码,8位
返回值:
K1:返回压缩后的密钥列表,56位
}
'''
K = StringToBit(keystring,mode)[0]
K1 = []
for i in range(56):
K1.append( K[PC1_table[i]-1])
return K1
#求密钥集合
def miyao(K,RoundNum=16):
'''
args = {
K:压缩后的密钥二进制字符列表,56位
RoundNum:轮数
返回值:
keylist:返回移位和置换选择2后的列表,包括没一轮的结果,形如[['0','1','0'.....]['0','0','0'....]],其中每个列表中有56位
}
'''
keylist = []
for j in range(RoundNum):
C = K[0:28]
D = K[28:56]
for i in range(left_rotations[j]):#移位
C.insert(len(C),C[0])
C.remove(C[0])
D.insert(len(D), D[0])
D.remove(D[0])
K.clear()
K = C+D
K1 = []
for i in range(48):#密钥置换选择2
K1.append(K[PC2_table[i]-1])
keylist.append(K1)
return keylist
#加解密函数
def DESEncrpty(text,keystring,Roundnum=16,way=1,mode=1):
'''
args = {
text:需要加密或者解密的字符串
keystring:密钥字符串
RoundNum:轮数
way:加密或者解密,1表示加密,2表示解密
mode:转换模式,如果为1,则使用十六进制;如果为2,则使用unicode编码,16位,可加密中文;如果为3,使用unicode编码,8位
返回值:
str1:返回加密或者解密后的字符串
}
'''
Bit = []
textBit = StringToBit(text,mode)
keybit = miyao1(keystring,mode)
if way==1:#加密时,密钥列表正用
keybitlist = miyao(keybit,Roundnum)
else:#解密时,密钥列表逆置
keybitlist = miyao(keybit, Roundnum)
keybitlist.reverse()
for i in textBit:#取64位bit串
text1 = []
for j in range(64):#初始置换
text1.append(i[IP_table[j] - 1])
L = text1[0:32]#左半部分
R = text1[32:64]#右半部分
print("初始置换后: 左:" + bitTTToString(L, 8) + " 右:" + bitTTToString(R, 8))
for j in range(Roundnum):#开始每轮的加密
temp = R.copy()
# print(R)
# print(keybitlist[j])
R = F_function(R,keybitlist[j])
for m in range(32):#左右两边异或得到下一轮右边
R[m] = L[m]^R[m]
L = temp#下一轮右边即为上一轮左边
print("第"+str((j+1))+"轮 "+"左:" + bitTTToString(L, 8) + " 右:" + bitTTToString(R, 8)+" 密钥:"+bitTTToString(keybitlist[j],12))
L,R = R,L#最后左右两边置换
print("左右两边交换后: 左:" + bitTTToString(L, 8) + " 右:" + bitTTToString(R, 8))
Bit1 = L+R
print("左右部分合在一起:"+bitTTToString(L+R,16))
Bit2 = []
for j in range(64):#逆初始置换
Bit2.append(Bit1[IP_Inverse_table[j] - 1])
print("逆初始置换后:" + bitTTToString(Bit2, 16))
Bit.append(Bit2)
#转换成密文字符串
str1 = BitToString(Bit,mode)
return str1
if __name__ == "__main__":
choice = 1
while choice:
choice = int(input("请输入选择[1]加密[2]解密[0]退出:"))
mode = int(input("请输入模式[1]十六进制[2]16位[3]8位:"))
Roundnum = int(input("请输入轮数:"))
if choice==1:
text = input("请输入需要加密的明文:")
key = input("请输入密钥(模式1输入16位,模式2输入4位,模式3输入8位):")
str1 = DESEncrpty(text,key,Roundnum,choice,mode)
print("加密后的字符串:"+str1)
elif choice==2:
text = input("请输入需要解密的密文:")
key = input("请输入密钥(模式1输入16位,模式2输入4位,模式3输入8位):")
str1 = DESEncrpty(text, key, Roundnum,choice,mode)
print("解密后的字符串:" + str1)
else:
break
#明文:123456ABCD132536
#密钥:AABB09182736CCDD
#密文:C0B7A8D05F3A829C```