python实现DES加密解密_des python 代码 16进制

这篇博客详细介绍了如何使用Python实现DES加密和解密过程,包括关键函数如IP置换、扩展置换、S盒子压缩、轮密钥加等,同时提供了完整的加密和解密函数实现。此外,还涵盖了密钥生成、0填充、密文处理以及16进制与字符转换等辅助功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

_IP_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
]

循环移位位数表

moveNum=[1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1]

IP置换函数

def IP(message):
result = ‘’
# 用IP表进行置换即可
for i in IP_table:
result += message[i-1]
return result

扩展置换函数

def extend(R0):
result=‘’
# 用扩展置换表进行置换即可
for i in extend_table:
result += R0[i-1]
return result

S盒子压缩函数

def sbox(afterRoundKey):
result = ‘’
for m in range(0,48,6):
# 通过第1位和第6位算出列号
i = int(afterRoundKey[m])*2+int(afterRoundKey[m+5])
# 通过第2、3、4、5位算出行号
j = int(afterRoundKey[m+1])*8+int(afterRoundKey[m+2])*4+int(afterRoundKey[m+3])*2+int(afterRoundKey[m+4])
result += str(‘{:04b}’.format(S[m//6][i][j]))
return result

轮密钥加函数

def addRoundKey(afterExtend,roundKey):
result = ‘’
for i in range(48):
# 进行按位异或运算
result += str(int(afterExtend[i])^int(roundKey[i]))
return result

线性置换P盒

def pbox(afterSbox):
result = ‘’
# 用P盒表进行置换即可
for i in range(32):
result += str(afterSbox[P_table[i]-1])
return result

F函数

def F(R0,key):
# 扩展将32位扩展为48位
R0 = extend(R0)
# 与轮密钥进行按位异或
afterRoundKey = addRoundKey(R0,key)
# 放入S盒压缩
afterSbox = sbox(afterRoundKey)
# 放入P盒进行线性替换
result = pbox(afterSbox)
return result

#轮密钥生成
def generateKey(key):
result = ‘’
roundKey=[]
# 进行第一次压缩置换,将64位密钥减至56位,即去除8个校验位
for i in PC_1:
result += key[i-1]
# 分位左右两部分,每部分28位
C0=result[:28]
D0=result[28:]
for i in range(16):
# 按循环移位位数表进行移位操作
C0=C0[moveNum[i]:]+C0[:moveNum[i]]
D0=D0[moveNum[i]:]+D0[:moveNum[i]]
tmp=C0+D0
ret = ‘’
# 进行第二次压缩将56位压缩减至48位
for i in PC_2:
ret+=tmp[i-1]
# 生成轮密钥存储到列表中
roundKey.append(ret)
return roundKey

IP逆置换

def inverseIP(afterF):
ciphertext=‘’
# 用逆IP表进行置换即可
for i in _IP_table:
ciphertext+=afterF[i-1]
return ciphertext

加密函数

def encrypt(plaintext,roundKey):
# 进行IP置换
result = IP(plaintext)
# 分左右32bit
L0=result[:32]
R0=result[32:]
# 进行16轮加密
for i in range(16):
tmp=R0
results = F(R0, roundKey[i])
# print(results)
# print(roundKey[0])
R0=‘’
for j in range(32):
R0+=str(int(L0[j])^int(results[j]))
L0=tmp
# print(R0)
# 最后一轮结束后结果要左右交换
afterF = R0+L0
# 进行逆IP置换得到密钥
ciphertext=inverseIP(afterF)
return ciphertext

解密函数

def decrypt(ciphertext, roundKey):
result = IP(ciphertext)
Li = result[:32]
Ri = result[32:]
# 解密函数对轮密钥使用要倒序使用
for i in range(15,-1,-1):
tmp=Ri
results = F(Ri,roundKey[i])
Ri = ‘’
for j in range(32):
Ri += str(int(Li[j])^int(results[j]))
Li = tmp
afterF = Ri+Li
plaintext = inverseIP(afterF)
return plaintext

0填充函数

def zeroPadding(message):
# UTF-8解码
message = list(bytes(message,‘utf8’))
# 先填充一个0,这使得如果明文本来就是64位仍然要填充64个0到末尾
message.append(0)
# 填充0到8字节的整数倍
while len(message)%8!=0:
message.append(0)
ret = []
strs=‘’
# 分组,化为二进制串,然后没8字节分组放入ret列表中
for i in range(len(message)):
strs+=str(‘{:08b}’.format(message[i]))
if (i+1)%8==0:
ret.append(strs)
strs=‘’
return ret

处理密文函数

def progress(cipher):
lens=len(cipher)
# 因为密文输入是16进制,所以直接按没16个字符分一组即可,最后会被解释成16*4=64bit
m=lens//16
ret=[]
for i in range(m):
ret.append(cipher[i*16:(i+1)*16])
return ret

将16进制位串变为字符

def to_chr(text):
lens = len(text)
# 每两个个16进制数被解释成一个ASCII码字符,2**8=256
m = lens // 2
lists = []
for i in range(m):
lists.append(text[i * 2:(i + 1) * 2])
strs = ‘’
for s in lists:
tmp=int(s, 16)
# 因为ascii码0不会被输入,因此认为是补位值,当存在补位值,后继必为补位值,直接舍弃即可
# 对中文进行加解密时这里需要优化
if tmp==0:
break
strs += chr(tmp)
return strs

if name == “__main__”:
print(“请选择1、加密,2、解密:”)
choose = input()
if choose == ‘1’:
message = input(“请输入要加密的文本:”)
key = input(“请输入密钥:”)
keylist = list(bytes(key, ‘utf8’)) # 将密钥变为ascii码
if len(keylist)!=8:# 密钥应该为8字节的整数倍
print(“错误!请输入8字节密钥!”)
else:
key=‘’
for i in keylist:
key += str(‘{:08b}’.format(i)) # 将密钥的ascii码转为2进制
roundKey = generateKey(key)# 生成轮密钥,用列表存储
lists=zeroPadding(message) # 进行明文0填充,并分组,每64位一组
cipher=‘’
for p in lists:
cipher+=encrypt(p, roundKey) # 每组分别加密,因为采用ECB方式,直接将各段加密结果链接即可
cipher=str(hex(int(cipher,2)))[2:] # 将结果2进制串转化为16进制串输出
print(cipher)
elif choose == ‘2’:
text = input(“请输入密文文本:”)
key = input(“请输入密钥:”)
keylist = list(bytes(key, ‘utf8’))
if len(keylist)!=8:
print(“错误!请输入8字节密钥!”)
else:
key = ‘’
for i in keylist:
key += str(‘{:08b}’.format(i))
roundKey = generateKey(key)
cipherlist=progress(text)
plaintext=‘’
for c in cipherlist:
message = str(‘{:064b}’.format(int(c, 16)))
tmp=decrypt(message, roundKey)
学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

一、Python所有方向的学习路线

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

二、学习软件

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

三、全套PDF电子书

书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。

四、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

五、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里无偿获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值