代码是从github上找到的,也融入了自己的一些理解。

一、原理

原理:分组密码将明文分成一组一组,在密钥的控制下,经过加密变换生产一组一组的密文。具体而言,分组密码就是将明文消息列m1,m2,···,mi,···划分成等长的消息组(m1,m2,···,mn),(mn+1,mn+2,···,m2n),···, 在密钥k1,k2,···,ki的控制下按固定的加密算法一组一组进行加密,输出一组一组密文(c1,c2,···cl),(cl+1,cl+2,···,c2l),···。

下面的实验以DES算法为例。DES算法明文分组长为64bit,加密后得到64bit密文,输入初始种子密钥为64bit,第8、16、24、32、40、48、56、64为奇偶校验位,实际的密钥长为56bit。DES加密过程由三个阶段来完成:

1) 初始置换IP,用于重排明文分组的64bit数据。

2) 相同结构的16轮迭代,每轮中都有置换和代换运算,第16轮变换的输出分为左、右两半,并交换次序。

3) 逆初始置换IP-1(为IP的逆)后,产生64bit的密文

流程图:

二、具体实现

下面给出加密思路:

  1. 首先第一步我们要从文件中读取明文;(1)
  2. 对明文进行字符转换成比特流,每64位分一组,最后不足的用0补齐;(2)
  3. 对每组的64位比特进行IP置换,分成L,R两组;(3)
  4. 对得到的L,R进行16轮的Feistel变换;(4)
  5. 再使用IP-1函数将L,R合并为密文比特流;(5)
  6. 最后将密文比特流转换成密文字符保存。(6)

解密的过程完全一样,不过是密钥逆用。故不再赘述。

接下来是加密实验过程:

(1).从文件中读取明文:

Python中内置了很多的库,在这里直接调用open函数来读取文本,选择r模式,表示只读操作

下面是代码:

def read_out_file():try:f = open('DES.txt','r',encoding = 'utf-8')mess = f.read()f.close()print("文件读取成功!")return messexcept IOError:print('文件加解密出错!!!')

(2).明文字符转换成比特流

每个英文字符都是有其对应的ascii码,再分组加密的时候,我们是在bit级上操作,因此先转化为bit流

下面是代码:

#字符串转化为二进制def str2bin(message):res = ""for i in message:  #对每个字符进行二进制转化tmp = bin(ord(i))[2:]  #字符转成ascii,再转成二进制,并去掉前面的0bfor j in range(0,8-len(tmp)):   #补齐8位tmp = '0'+ tmp   #把输出的b给去掉res += tmpreturn res

(3)IP函数置换

下面进入到了核心的加密环节。第一步比较简单,将比特流进行IP置换,核心其实就是置换的IP盒,将明文比特流中的每一位,按照IP盒中的顺序,重新排序:即盒中第x位数字为y,表示将64一组的明文比特流的第y位,放在x位。

下面仅给出置换函数的核心部分,不再赘述IP盒:

#IP盒处理def ip_change(bin_str):res = ""for i in IP_table:res += bin_str[i-1]     #数组下标i-1return res注:得到比特流后,可以进行切片操作,即可得到L,R两部分。如下:mes_left = res[0:32] 表示切从0到32,但不包括32mes_right = res[32:]   表示32开始,到之后全部

(4)一轮的Feistel变换

DES中最最最核心的就是此处的变换,需要重复做16轮,因此我们只需要明确一轮即可:

即密钥子密钥Ki与Ri-1进行f函数变换,得到的结果再与Li-1进行异或。

所以我们明确我们需要完成的事:

首先根据密钥生成子密钥;(①)

子密钥与R的f函数实现;(②)

异或函数的实现。(③)

  • 密钥我们也是按照64位一组进行的划分,有64位,其实有效位仅为56位,需要通过PC-1盒先选择出有效的该56位:
#秘钥的PC-1置换def change_key1(my_key):res = ""for i in PC_1:  #PC_1盒上的元素表示位置    只循环64次res += my_key[i-1]     #将密钥按照PC_1的位置顺序排列,return res

如明文一样,这里也需要分为左右两部分,每个子部分28位

对该28位,进行重复左移,第LS1,LS2,LS9,LS16次是循环左移1位变换,其他为循环左移2为变换

这里将循环左移的位数,写在一个列表SHIFT中,方便调用,每一轮左移,都会得到一个56位子密钥,需要再通过PC-2选择出最终的48比特的子密钥

下面给出代码实现: 

   for i in SHIFT:   #i是左移位数    SHIIFT元素个数为循环次数key_c = left_turn(key_C0,i)   #左半部分循环左移key_d = left_turn(key_D0,i)   #右半部分循环左移key_output = change_key2(key_c + key_d) #将左移后的密钥合并后使用PC-2盒置换出48位key_list.append(key_output)    #将第i个子密钥添加到列表保存
  • 如上我们得到了16个子密钥,并存放在了列表中待用,接下来需要完成f函数的功能,这是DES的核心中的核心了,f函数实现的功能是:

先将明文32bit拓展为48bit,然后与子密钥Ki进行按位模加运算(即异或),得到的结果按每组6位分为8组,再经过S盒,从每6位中选择出4位,得到32比特,经过P盒置换后,得到最终的32位结果。

那么,我们要先实现明文拓展的功能,这里我们使用E盒,将明文的部分bit重复排列,造成冗余,来实现拓展:

#E盒置换def e_str(bin_str):res = ""for i in E:res += bin_str[i-1]return res

现在得到了48位明文bit,可以与子密钥进行异或运算,如下:

#字符串异或操作def str_xor(my_str1,my_str2):  #str,keyres = ""for i in range(0,len(my_str1)):xor_res = int(my_str1[i],10)^int(my_str2[i],10) #变成10进制是转化成字符串 2进制与10进制异或结果一样,都是1,0if xor_res == 1:res += '1'if xor_res == 0:res += '0'    #字符串连接return res

异或运算结束后,我们需要将48bit缩减位32bit,分组使用S盒置换,如下:

# S盒过程def s_box(my_str):res = ""c = 0for i in range(0,len(my_str),6):#步长为6   表示分6为一组,会循环8次now_str = my_str[i:i+6]    #第i个分组,切片划入row = int(now_str[0]+now_str[5],2)   #b1b6 =r   第r行   共4行col = int(now_str[1:5],2)   #第c列   共16列# s盒的第几个表的  第row*16+col个位置的元素num = bin(S[c][row*16 + col])[2:]   #利用了bin输出有可能不是4位str类型的值,所以才有下面的循环并且加上字符0for gz in range(0,4-len(num)):num = '0'+ numres += numc  += 1   #S盒的下一个表return res     #循环结束后。返回得到的32位结果

下面将上一步得到的结果,经过P盒置换,还原出正确的序列:

#P盒置换def p_box(bin_str):res = ""for i in  P:res += bin_str[i-1]return res
  • 其实在f函数中,我们已经使用了异或函数,这里我们需要再次使用其,将上一步的结果,与L异或操作,下面不再赘述。

上面我们已经完成了一轮的Feistel变换,再下一轮时,Li = Ri-1 ;Ri =Li-1⨁ f(Ri-1,Ki)即③得到的结果。

需要注意的是,在最后一轮变换后,不用交换位置了。

(5)IP-1 函数将加密后的L,R合并为密文比特流

终于,经过了前面的16轮变换,最后一轮不用交换左右两部分,直接合并比特流,得到了加密后的56位比特,现在我们要使用初始置换函数的逆函数,得到正确的密文序列。也是直接从盒中置换,不再赘述。

(6)将密文比特流转化为密文字符

这里用到了也是和之前函数相反的功能。这里将比特流转化为字符串:

#二进制转化为字符串def bin2str(bin_str):res = ""tmp = re.findall(r'.{8}',bin_str)  #每8位表示一个字符for i in tmp:res += chr(int(i,2))  #base参数的意思,将该字符串视作2进制转化为10进制return res

将密文写回文本:

def write_in_file(str_mess):try:f = open('DES.txt','w',encoding='utf-8')f.write(str_mess)f.close()print("文件输出成功!")except IOError:print('文件加解密出错!!!')

下面,来总结下我们的编码思路,看代码:(每次编码64bit即8byte)

def des_encrypt_one(bin_message,bin_key): #64位二进制加密的测试

    mes_ip_bin = ip_change(bin_message)  #ip转换

    key_lst = gen_key(bin_key)   #生成子密钥

    mes_left = mes_ip_bin[0:32]

    mes_right = mes_ip_bin[32:]

    for i in range(0,15):

        mes_tmp = mes_right  #暂存右边32位

        f_result = fun_f(mes_tmp,key_lst[i])   #右32位与k的f函数值

        mes_right = str_xor(f_result,mes_left)  #f函数的结果与左边32位异或   作为下次右边32位

        mes_left = mes_tmp   #上一次的右边直接放到左边

    f_result = fun_f(mes_right,key_lst[15])  #第16次不用换位,故不用暂存右边

    mes_fin_left = str_xor(mes_left,f_result)

    mes_fin_right = mes_right

    fin_message = ip_re_change(mes_fin_left + mes_fin_right)   #ip的逆

return fin_message   #返回单字符的加密结果

如上我们是每次只能编码64bit,所以我们还要对明文和密钥进行处理,使其成为64的倍数,保证每次都有足够的比特可操作:

#简单判断以及处理信息分组def deal_mess(bin_mess):ans = len(bin_mess)if ans % 64 != 0:for i in range( 64 - (ans%64)):           #不够64位补充0bin_mess += '0'return bin_mess

同理:

#查看秘钥是否为64位def input_key_judge(bin_key):ans = len(bin_key)if len(bin_key) < 64:if ans % 64 != 0:for i in range(64 - (ans % 64)):  # 不够64位补充0bin_key += '0'else:bin_key = bin_key[0:64]    #秘钥超过64位的情况默认就是应该跟密文一样长 直接将密钥变为跟明文一样的长度,虽然安全性会有所下降return bin_key 

得到了恒为64倍数的明文,和密钥比特流后,我们可以使用下面这条正则表达式:

tmp = re.findall(r'.{64}',bin_mess) 

将我们的实际很长的明文匹配位每64位一组的列表,每次对列表中的项进行加解密即可!!!

                                                                           <加密完>

关于解密,因为原理完全相同,仅仅是密钥选择顺序不同,此处仅给出原理代码:

##64位二进制解密的测试,注意秘钥反过来了,不要写错了def des_decrypt_one(bin_mess,bin_key):mes_ip_bin = ip_change(bin_mess)#bin_key = input_key_judge(str2bin(key))key_lst = gen_key(bin_key)lst = range(1,16)   #循环15次cipher_left = mes_ip_bin[0:32]cipher_right = mes_ip_bin[32:]#------------------------------------重点-------------------------------------for i in lst[::-1]:   #表示逆转列表调用#----------------------------------------------------------------------------------mes_tmp = cipher_rightcipher_right = str_xor(cipher_left,fun_f(cipher_right,key_lst[i]))cipher_left = mes_tmpfin_left = str_xor(cipher_left,fun_f(cipher_right,key_lst[0]))fin_right = cipher_rightfin_output  = fin_left + fin_rightbin_plain = ip_re_change(fin_output)res = bin2str(bin_plain)return res

三、结果测试

运行程序,测试其可行性与正确性,如下:

可以看出已经可以实现我们的实验要求功能,并能够将密文,输出到文本文件,便于下次读取,不用重复输入。

修改后的放在自己的Github上,需要自提:传送门

附:原作者的循环左移函数本人认为有些问题,遂做了简单修改。

还是要一如既往的努力,没有富婆能看穿你的逞强,明天的砖只会比今天的更烫手!!!

加油!

DES加解密的python实现相关推荐

  1. 用python实现DES加解密,并附带EBC和CBC两种分组加密模式

    之前在网上看了好多关于DES加解密的文章,很多都是直接贴代码,然而大多数都不能运行.花了一天写了个能运行的程序,其中有参考网上的一些好的代码.希望入了密码学坑的同学能得到帮助.python刚上手,代码 ...

  2. PHP 基础篇 - PHP 中 DES 加解密详解

    2019独角兽企业重金招聘Python工程师标准>>> 一.简介 DES 是对称性加密里面常见一种,全称为 Data Encryption Standard,即数据加密标准,是一种使 ...

  3. 一个java的DES加解密类转换成C#

    原文:一个java的DES加解密类转换成C# 一个java的des加密解密代码如下: //package com.visionsky.util;import java.security.*; //im ...

  4. 密码学入门1——凯撒密码和三重DES加解密

    实验目的 1.完成第一个入门加解密--凯撒密码 2.完成当下较为流行的三重DES加解密技术 3.熟悉所学的实际运用方向 实验准备 硬件:计算机或笔记本电脑 操作系统:Mac操作系统 IDE环境:Ecl ...

  5. C语言实现DES加解密算法

    C语言实现DES加解密算法 DES加解密 DES加解密 #include <stdio.h> #include <stdlib.h> #include <string.h ...

  6. js des加密 java_Java实现与JS相同的Des加解密算法完整实例

    本文实例讲述了Java实现与JS相同的Des加解密算法.分享给大家供大家参考,具体如下: 这里演示java与js实现相同的des加解密算法,不多说,不废话,直接上代码 一.java实现 package ...

  7. LKT系列加密芯片DES加解密以及OpenSSL DES接口实现加解密

    1.测试目标 使用已经预置DES密钥的LKT4201N系列加密芯片完成运算 2.测试环境 本示例运行环境为windows系统.测试软件LCS KIT.LKT-K100开发板. 3.测试步骤 注意:&q ...

  8. Hutool进行DES加解密

    Hutool进行DES加解密 先简述以下:一个数据接口,接收到的是DES加密后的json字符串,需要先解密再转成bean对象. 我试了网上很多方式实现,发现每次加密后最后几位不同.想着对称加解密还能这 ...

  9. java 和 c# 下的RSA证书+AES+DES加解密实现

    java 和 c# 下的RSA+AES+DES加解密实现 前言 在实际应用中,经常有需要使用加解密的情况,RSA\AES\DES是比较常用的几种加解密方式,使用和实现方式都比较成熟可靠,本文简要介绍一 ...

最新文章

  1. 线程工具类(根据电脑逻辑处理器个数控制同时运行的线程个数)
  2. HarmonyOS之AI能力·文字图像超分
  3. 数据结构基础 - 链表的遍历
  4. 64位Visual Studio 2022,微软在下一盘大棋!
  5. HTML.ActionLink 和 Url.Action 的区别
  6. 程序设计与算法----递归之爬楼梯问题
  7. 九度搜索引擎点击优化_深圳坂田企业老总在想竞价推广和网站优化选哪个?
  8. C语言system函数使用
  9. 小程序点击图片全屏播放视频
  10. CS5263芯片 DP转HDMI视频转换芯片 适用于HDMI单转线
  11. NVIDIA JETSON NANO三个版本核心的对比
  12. PS 给给人物磨皮(美白)
  13. lmdb文件的读取和保存
  14. java基础知识学习小总结(一)
  15. 新课程上线 | 学习使用 Kotlin 进行 Android 开发的最佳时机!
  16. 3601lpk.dll劫持病毒分析
  17. xiang cheng
  18. 基于stm32的DHT11温湿度采集LCD显示Proteus仿真
  19. Mac窗口管理软件合集|告别混乱屏幕,一切井井有条。
  20. 计算机等级考access,计算机等级考试二级ACCESS窗体

热门文章

  1. Java小农养成记第八天
  2. ios生成随机数方法
  3. 【温故而知新】分布式系统(二)
  4. 天气灾害预警 API接口 查询灾害预警内容
  5. 基于matlab的立体图像编码解码算法仿真与分析
  6. android的系统优势,安卓新系统也有优势! 对比iOS一点也不输
  7. 迈拓恢复出厂设置图解_电脑系统怎么重置呢?教你恢复出厂设置
  8. android 贴身检测,安卓5.0贴身检测怎么设置_安卓贴身检测智能解锁设置方法_飞翔教程...
  9. springboot集成京东物流查询快递,运费,标价运费
  10. 用户画像----对于标签的快速匹配