Des加密原理与简单实现

2023-11-16

源码:https://gitee.com/Cheney822/programmes/blob/master/des.py

摘要

实验利用Python语言实现了des加密和解密的功能,并封装成一个类方便后续调用。程序可以读取由数字、符号、字母和中文组成的字符串,并将其转换成二进制在程序内部处理。程序需要的密钥为64位二进制,处理的明文为64的整数倍,对于读入的密钥和明文,转换后不足64位的补0补到64位,超过64位的密钥直接丢弃,超过64位的明文补0补到64的整数倍。

程序为了能够处理中文,采用utf-8编码,读入的明文经过编码转为二进制交由函数处理得到密文,由于加密后的密文不一定符合utf-8编码规则,若使用utf-8解码会得到不可识读、无法输出的字符,故对加密后的二进制密文做base64转换成字符串,输出给用户。解密过程是上述过程的逆过程,首先读入密文字符串,然后利用base64解码,得到的密文二进制序列交由函数处理得到明文字二进制。最后由utf-8编码输出原明文字符序列。

程序预留了调试信息的输出接口,可支持三级中间信息的输出。默认为0级不做任何调试信息的输出,1级仅输出少量重要信息,二级输出全部详细调试信息。

程序采用了多线程并行的设计,加密和解密的过程中要把源文本二进制每64位为一个部分投入一个独立的线程进行处理,最后各个线程处理的结果拼接为最终结果。并预留接口可以实现多线程模式的开/关。

背景

*数据加密*,指的是根据一定规则,将数据处理成不规则的数据,使得人们除非有了关键的钥匙以及得知这个规则,难于得知无规则数据的真实含义。这个一定规则 就是加密算法,这个钥匙就是密钥。

*数据加密分为对称密钥加密以及非对称密钥加密:*

对称密钥加密: 双方共同持有这个密钥,发送方用这个密钥按照指定的算法将数据加密,再发出去;接收方用这个密钥将接收到的数据解密,以得到真实的数据含义。由于双方都持有这个密钥,而且内容相同,所以叫对称密钥

非对称密钥加密:这种加密方式的密钥是一对,发送方用其中的一把钥匙将数据加密,再发出去;接收方用这对密钥的另一把钥匙将数据解密,以得到真实的数据含义。发送方持有密钥中的一把钥匙,接收方持有另外一把。接收方持有的钥匙叫 私钥, 而接收方持有的这把钥匙叫公钥 。两把钥匙不一样,所以叫做非对称密钥加密,也叫做公开密钥算法。

*对称密钥加密:*

对称密钥加密又叫专用密钥加密或共享密钥加密,即发送和接收数据的双方必使用相同的密钥对明文进行加密和解密运算。对称密钥加密算法主要包括:DES、3DES、IDEA、RC5、RC6等。

对称密钥加密是双方使用相同的密钥,必须以绝对安全的形式传送密钥才能保证安全。若果密钥泄露,加密数据将受到威胁,这点不如非对称密钥。

发送方和接收方必须用安全的方式来获得密钥和保存密钥,必须保证密钥的安全。如果有人发现了密匙,并知道了算法,则使用此密匙加密的所有数据便都是可被窃取。即使分析人员拥有一些密文和生成密文的明文,也不能译出密文或者发现密钥。加密算法应足以抵抗已知明文类型的破译。

des加密

DES是美国国家标准和技术局(NIST)在1977年才有的数据加密标准,DES的思路就是参照二战时期盟军缴获的德军恩格玛加密机,当然更为复杂和严谨,文件编号为FIPS PUB46。老牌而强悍的加密算法,广泛地使用使其颇具名气。算法本身称为DEA(数据加密算法)。DES是最常用的对称加密算法。DES密匙长度为56位,分组长度为64位。为了提高加密强度,后来又发展出三重DES加密,即3DES。

其加密运算、解密运算使用的是同样的密钥,信息的发送者和信息的接收者在进行信息的传输与处理时,必须共同持有该密码(称为对称密码),是一种对称加密算法。

DES 使用一个 56 位的密钥以及附加的 8 位奇偶校验位,产生最大 64 位的分组大小。这是一个迭代的分组密码,使用称为 Feistel 的技术,其中将加密的文本块分成两半。使用子密钥对其中一半应用循环功能,然后将输出与另一半进行“异或”运算;接着交换这两半,这一过程会继续下去,但最后一个循环不交换。DES 使用 16 个循环,使用异或,置换,代换,移位操作四种基本运算。

*主要流程是:*

  • 将明文分组

  • 对每个分组进行初始字节置换

  • 生成对应的子密钥

  • 对每一个迭代进行置换,异或运算等运算,得到分组密文

  • 迭代直到完成全部迭代过程

DES算法具有极高安全性,到目前为止,除了用穷举搜索法对DES算法进行攻击外,还没有发现更有效的办法。而56位长的密钥的穷举空间为256,这意味着如果一台计算机的速度是每一秒种检测一百万个密钥,则它搜索完全部密钥就需要将近2285年的时间,可见,这是难以实现的,当然,随着科学技术的发展,当出现超高速计算机后,我们可考虑把DES密钥的长度再增长一些,以此来达到更高的保密程度。

Des类概要设计

接口

类支持的参数列表如下:

:param key: 加密或解密的密钥 只取输入密钥对应二进制的前64位 其他丢弃
:param plaintext: 明文 任意长度的任意内容
:param secrettext: 密文 任意长度的经过本程序加密的内容
:param is_debug: 是否输出调试信息 0表示不输出 1仅输出重要信息 2输出详细信息  默认不输出
:param use_threading: 是否使用多线程的方式 0表示不用  默认使用

其中只有密钥key是必要参数(因为需要在构造函数内执行16个子密钥的初始化工作),其他参数均设有默认值。明文和密文两个参数也可以在调用加密/解密函数的时候给出,如果两处都给出那么函数内的参数会覆盖初始化的参数。

函数

*Des类的成员函数如下:*

image-20220323212338470

执行逻辑

image-20220323212358069

详细设计

初始化__init__函数

在函数里内进行一系列的初始化操作。

参数列表:
:param key: 加密或解密的密钥 只取输入密钥对应二进制的前64位 其他丢弃
:param plaintext: 明文 任意长度的任意内容
:param secrettext: 密文 任意长度的经过本程序加密的内容
:param is_debug: 是否输出调试信息 0表示不输出 1仅输出重要信息 2输出详细信息  默认不输出
:param use_threading: 是否使用多线程的方式 0表示不用  默认使用
  • 首先处理类的初始化时接收到的参数,将其依次赋给成员变量。

  • 然后定义再定义两个成员变量:lock和key_48_mat,分别表示多线程时用到的锁以及十六个48位的子密钥。

  • 最后调用成员函数get_key_48用来根据参数key生成十六个子密钥,即完成对key_48_mat的初始化工作。

置换功能的实现

由于程序中多处用到置换功能(比如PC1置换、IP置换、E拓展等),故将此功能抽象成函数方便复用。

用table表对source做置换 得到 置换后的列表ans
:param source: 要进行置换的列表(不会直接影响这个列表的内容)
:param table: 里面储存的是置换的规则 如:PC1,IP
:return: 新的 置换后的列表        

函数replace的功能是把source表内的明文按照table表中的规则进行替换,生成替换后的新表。

子密钥生成

用来初始化key_48_mat,由输入的密钥生成每轮需要用的密钥
:param key: 用户输入的密钥
:return: 每轮需要用的密钥key_48_mat

子密钥生成分为以下几步:

  • 第一步,先把密钥中的奇偶校验为去掉,然后根据选择置换PC-1讲剩下的密钥分成两块C0和D0;
  • 第二步,将C0和D0进行循环左移变换,变换后生成C1和D1,然后C1和D1合并,通过选择置换PC-2生成子密钥K1;
  • 第三步,C1和D1再次经过循环左移变换,生成C2和D2,C2和D2合并,通过选择置换PC-2生成子密钥K2;
  • 第四步,以此类推,需要注意其中循环左移的位数,一共是循环左移十六次,其中LS1(第一次),LS2(第二次),LS9,LS16是循环左移一位,其他的都是左移两位。
image-20220323212501344

轮函数

对输入的32位数据, 做当前轮对应的操作 E拓展/异或/S盒/P置换

:param text_32: 输入的32位数据
:param round: 轮次
:return: 最后处理完的32位数据

*轮函数加密过程分为以下几步:*

  • 第一步,将R0通过位选择函数E置换,其实这是一个扩充的置换,因为R0本身是32位的,而生成的子密钥是48位的,因此需要扩充一下,方能按位运算。
  • 第二步,将扩充完的R0和子密钥K1进行模2加运算,得到48位的一个串,把这个串从左到右分为8组,每组6个字符。这里设8组分别为B1,B2,B3,B4,B5,B6,B7,B8。其中Bj=b1b2b3b4b5b6。
  • 第三步,通过S盒来收缩,把每组中的b1b6放一块,换算为十进制,b2b3b4b5放一块,也换算为十进制。b1b6代表S盒中的行标,b2b3b4b5代表列标。比如说B1=011111,那么b1b6就等于十进制的1,b2b3b4b5等于十进制的15,也就是对应表中的S1块中的第1行(注意不是0行),15列,也就是8,然后把8变为二进制1000。这就完成了S盒收缩变换,然后通过S盒输出的就是32位的一个串。
  • 第四步,把32位的串经过置换函数P的置换得到的结果就是这个核心函数的产物了。
image-20220323212514302

主循环

:param sourcetext_64: 源操作文本  targettext目标文本
:return: 返回对原文本处理的结果 即targettext

在这个函数内部做加/解密的主操作,包括:IP置换、16轮迭代(调用轮函数)、异或、前后颠倒、IP逆置换。(传入的参数和产生的结果都是64位二进制)

*具体的步骤:*

  • 首先对64位的二进制源操作文本进行IP置换。
  • 然后将其分离成左右两部分,并将右半部分投入轮函数运行,左半部分的内容保留下来。
image-20220323212528603
  • 轮函数的返回值仍然是32位的二进制,用上述分离出的左半部分与其异或得到最终的右半部分,然后与保留的左半部分结合。循环执行上述操纵,直至完成十六轮操作。
  • 十六轮操作结束之后,将前后两半部分颠倒。
  • 最后IP逆置换 得到二进制密文
image-20220323212544039

二进制与字符串转换

程序涉及到的二进制转文本和文本转二进制分别由bit64_to_text以及text_to_64bit完成。

text_to_64bit完成的任务是将传入的text转换成若干个长度为64的由0/1组成的字符串(不足的补0),并由列表的形式返回。操作步骤:

  • 首先判断传入的是不是bytes类型,不是则用encode方法将其解码为bytes

  • 然后遍历整个bytes类型的text,逐元素转为二进制(每个元素为8bit)

  • 判断处理完64个bit则将64bit拼接成一个字符串并加入列表

  • 如果bytes不足64整数倍,则在最后一个元素内补0补到64位

  • 重复上述步骤直至遍历结束返回列表

bit64_to_text完成的任务是将二进制列表转化成可读的句子。此函数主要为密文的显示服务,由于加密的结果不再符合utf8的编码规则,所以每八个bit转一个八进制,然后再将其转为byte类型并返回,外围函数最终会将此bytes类型变量转为可读的字符串。

加/解密

加密函数(encryption):首先将用户传入的明文(字符串)用text_to_64bit函数转为二进制列表,然后遍历整个列表,将元素逐个用main_frame函数处理,如果开启了多线程则还要将main_frame投入一个新的线程中去运行。

由于得到的二进制密文较长,而且由于加密的结果是混乱不可读的,无法用utf8解码,所以使用bit64_to_text函数进行转换的话会得到不可识别的字符,故这里采用base64编码将二进制密文转换成较短的文本返回给优化。

等待所有子线程后,将得到的二进制用base64.b64encode函数转换为base64编码,然后以字符串的格式返回给用户。

image-20220323212608354

解密(decryption)的过程就是上述过程的逆过程,核心部分与DES的加密过程完全相同,只不过将16轮的子密钥序列K1,K2……K16的顺序倒过来变成K16,K15……K ,代码实现也十分简单,只需运行reverse()方法即可。

需要注意的是程序内部处理的均为二进制(字符串格式的01序列),而读入和输出的都是具有一定可读性的字符串。所以在读入后和输出前都要做一定的处理。具体流程如上图所示。

多线程的实现

import threading
threading.Thread(target=self.main_frame, args=[plaintext_64_bit_mat[ii], ii, ]).start()
threading.Thread(target=self.main_frame, args=[secrettext_64_bit_mat[ii], ii, ]).start()

由于程序主循环每次只能处理64位的数据,而需要处理的数据往往远大于64。所以采用切片分别处理的方式来处理,即把要处理的数据切成大小为64bit的片段(不够的末尾补0),分别投入函数处理然后再把处理完的结果拼接起来作为最终结果输出(如下图)

image-20220323212634530

由于多个片段的处理是互相独立的,所以采用多线程并行的方式来加快运行速度。即每次将一个64位的片段作为参数传递给main_frame处理,然后将这个函数投入新的线程中去运行,注意python中threading.Thread传参的格式。

由于线程之间的资源是共享的所以存在临界资源访问的问题,注意要互斥的访问公共的资源。设置类的成员lock表示锁的值,除此以外本程序中不涉及到公共资源的写入问题。Lock的初始值为子线程的总数,在生成子线程之前确定,每次有一个线程完成任务就要主动的将锁的值减一。在程序执行到后续的步骤时,需要主线程等待所有子线程将任务处理完毕,只需要在主线程中循环判断lock的值是否为0即可。

程序预留了多线程的开关,只需要在实例化对象的时候传入参数use_threading=0/1即可,实现多线程的关/开。注意如果打开了程序输出调试信息的选项,那么就会自动关闭多线程模式,因为多线程下会乱序输出调试信息,导致信息不可读。

运行测试与使用手册

首先调用接口,实例化des对象,然后使用des对象内的加密和解密方法进行数据的加密和加密。

加密

加密要调用encryption函数,若在实例化对象时已经输入了明文和密钥,则调用函数时不再需要给参数,如果实例化时没有给出明文,则需要再给出明文参数,如果两处都给出了参数,则encryption函数处传入的参数会覆盖掉实例化时给出的参数,如果两处都没有参数,则会采用程序内置的默认参数。

本程序在测试时明文和密钥都在实例化的时候传入参数,在调用函数时不再传入参数。

PlainText = input("请输入要加密的明文:\t")
DES = des(Key, plaintext=PlainText)  # 定义DES对象
SecretText = DES.encryption()
image-20220323220358719

正确解密

只需要先定义des对象,然后调用对象的decryption方法即可。解密的参数调用和加密相同。

SecretText = input("请输入要解密的密文:\t")
DES = des(Key, secrettext=SecretText)  # 定义DES对象
PlainText = DES.decryption()
image-20220323220423794

错误密钥解密

密钥错误会无法还原出可读的明文,程序会提示错误

图片1

错误密文解密

密文错误会无法还原出可读的明文,程序会提示错误

img

关闭多线程模式

加入参数 use_threading=0

SecretText = input("请输入要解密的密文:\t")
DES = des(Key, secrettext=SecretText, use_threading=0)  # 定义DES对象
PlainText = DES.decryption()
image-20220323220942362

输出简略调试信息

加入is_debug=1参数。

SecretText = input("请输入要解密的密文:\t")
DES = des(Key, secrettext=SecretText)  # 定义DES对象
PlainText = DES.decryption()

程序会输出生成的十六个子密钥,以及每一轮操作的中间结果

image-20220323221011409 image-20220323221024674

输出详细调试信息

参数列表同上,但is_debug=2。

输出上述所有中间结果的同时会输出轮函数内部每一步的中间结果。

img img

因为输出内容较多,整个算法用时也会大幅上升。

img
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Des加密原理与简单实现 的相关文章

随机推荐

  • GIOU:Generalized Intersection over Union: A Metric and A Loss for Bounding Box Regression

    废话不多说 先看motivation There is a gap between optimizing the commonly used distance losses and maximizing this metric value
  • 高并发应用实践——缓存简介

    简介 随着互联网的普及 内容越来越复杂 用户和数据量越来越大 所以我们的应用应该支持更高的并发数 但是由于我们的服务器和数据库服务器资源量是有限的 所以如何更加高效的利用这有限的资源 并提供尽可能大的数据吞吐量 一个有效可行的办法就是引入缓
  • shell调用php脚本,并传递参数

    命令行执行带参数的php脚本 并取得参数 张映 发表于 2011 07 15 分类目录 php 一 为什么我们要在命令行下运行php脚本呢 个人理解 主要有二个原因 1 利用crontab去跑php 可以给服务器减压 当然在这里有一个条件
  • 如何导出mysql数据库

    mysql数据库是非常常用的一种数据库 属于中小型数据库 常用于网站业务和一些WEB系统业务 这个数据库非常简单 体积比较小 使用起来比较方便简洁 今天重点来介绍一下该数据的三种导出方法 1 使用工具软件导出数据库文件 这里推荐使用navi
  • ElementUI浅尝辄止30:PageHeader 页头

    如果页面的路径比较简单 推荐使用页头组件而非面包屑组件 1 如何使用
  • 信号处理之FFT(如何求幅度、相位、画频谱图)

    信号处理 可以理解为对信号进行某种加工或变换来达到削弱信号中的多余内容 滤除混杂的噪声和干扰 将信号变换成容易分析与识别的形式 便于估计和选择它的特征参量等目的 快速傅里叶变换 FFT 是信号处理的重要组成部分 是离散傅里叶变换 DFT 的
  • Python调用MMDetection实现AI抠图去背景

    这篇文章的内容是以 使用MMDetection进行目标检测 实例和全景分割 为基础 需要安装好 MMDetection 的运行环境 同时完成目标检测 实例分割和全景分割的功能实践 之后再看下面的内容 想要实现AI抠图去背景的需求 我们需要利
  • JavaWeb-13-Tomcat&Servlet学习笔记

    JavaWeb 13 Tomcat Servlet Web核心模块 1 web相关概念回顾 1 1软件架构 1 2资源分类 1 3网络通信三要素 2 web服务器软件 2 1常见的java相关的web服务器软件 2 2Tomcat web服
  • RDP远程桌面密码凭证获取

    前言 在渗透过程中获取到一台Windows服务器后 可以尝试获取当前机器保存的RDP远程桌面密码凭证 进而在内网横向渗透中进一步扩大战果 0x01 密码凭证获取 查看当前主机本地连接过的目标机器记录 reg query HKEY CURRE
  • 设置useSSL=true 的出现的问题

    一 环境 springboot mybaits plus mysql linux 服务器 服务器修改了SSL配置 对应的服务需要修改 二 问题1 Access without SSL denied Caused by java sql SQ
  • Base64图片编码的使用

    一 base64编码介绍 二 base64图片使用介绍 三 base64图片编码大小与原图文件大小之间的联系 四 代码实现 一 base64编码介绍 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一 Base64编码可用于
  • JUC学习系列六(计数器 CountDownLatch)

    一个同步辅助类 在完成一组正在其他线程中执行的操作之前 它允许一个或多个线程一直等待 用给定的计数 初始化 CountDownLatch 由于调用了 countDown 方法 所以在当前计数到达零之前 await 方法会一直受阻塞 之后 会
  • 以一己之力搭建分布式ChatGPT

    原以为去年年底ChatGPT已经火过一阵子了 慢慢热度会降下来 出乎意料的是 其热度有增无减 我也是从去年年底一直关注并使用 包括ChatGPT网页版 GPT3 API以及ChatGPT内测API 还包括其他国内外一些人工智能算法的体验 为
  • python回声程序_python 包详解

    包 包是一种管理 Python 模块命名空间的形式 采用 点模块名称 比如一个模块的名称是 A B 那么他表示一个包 A中的子模块 B 就好像使用模块的时候 你不用担心不同模块之间的全局变量相互影响一样 采用点模块名称这种形式也不用担心不同
  • pyspark修炼手册(长期帖)

    2020 03 31 在进行pyspark开发时 需要先安装hadoop spark的环境 或者只安装spark环境即可 配置集群or单机环境都可以 在配置好环境后 不需要单独启动hadoop spark 直接运行pyspark程序即可 一
  • 初学STM32之定时器中断

    初学STM32之定时器中断 一 定时器概述 1 定时器的分类 STM32F10x系列总共最多有8个定时器分为高级定时器 通用定时器和基本定时器 三种定时器的主要区别如下图所示 本文章仅介绍通用定时器的一些知识 2 通用定时器功能概述 通用定
  • c语言实验5循环结构程序,C语言学习知识循环结构程序设计实验报告.doc

    C语言学习知识循环结构程序设计实验报告 doc 甘肃政法学院本科生实验报告 五 姓名赵明翔学院公安技术学院专业安全防范工程班级 2015级安全防范工程班实验课程名称程序设计实验日期2016年月日开课时间2015学年第二学期实验题目实验5 循
  • ios链式编程

    首先我们看一下使用Masonry对控件进行布局的代码格式 self bottomView1 mas makeConstraints MASConstraintMaker make make left mas equalTo 20 make
  • 不坑盒子 + 智能写作(Office、WPS插件)助你高效办公,早点下班回家。

    不坑盒子简介 很多朋友在工作过程中需要对Word文档进行编辑处理 如果想让Word排版更有效率可以试试小编带来的这款不坑盒子软件 这是一个非常好用的插件工具 专门应用在Word文档中 支持Office 2010以上的版本 用户可以借助工具快
  • Des加密原理与简单实现

    源码 https gitee com Cheney822 programmes blob master des py 摘要 实验利用Python语言实现了des加密和解密的功能 并封装成一个类方便后续调用 程序可以读取由数字 符号 字母和中