Python DES加密实现原理及实例解析


Posted in Python onJuly 17, 2020

加密流程

​首先说一下置换的意思,比如说有5678这个字符串,置换表为2143,置换表中的数表示的是位置,所以字符串变成6587。所有的置换表在程序中。(S盒置换不一样,会另外说明)

密钥部分

Python DES加密实现原理及实例解析

  • 把8位字符串密钥变成2进制(好像密钥只可以是8位,这一块我也没有搞太清楚)
  • 64位密钥进行PC1置换,变成56位,因为以前DES是用硬件实现的,所以8,16,24,32,40,48,56,64位为校验位,不记入密钥部分。但是我们现在是用软件实现,所以这8位需要去掉,再打乱顺序。
  • 将56位密钥对半分L0和R0、分别对L0和R0进行左循环移位,(当轮数为第1、2、9、16轮时,移动1位,其余时候移动两位)L0,R0移动1位后得到L1,R1。L1和R0继续进行下一轮,进行16轮。
  • 上面移位得到的所以Li+Ri进行PC2置换得到16个子密钥(PC2置换把56位数据变成了48位)。

明文部分

  • 先进行明文填充,采用PKCS #5规则,如果刚好满足每组有8个字节,则再添加一组,每个字节为000010000,如果最后一组没有8个字节,则把这一组填充成8个字节,填充的字节为少掉的字节的数目,比如有7个字节,则填充00000001。
  • 再进行初始置换,把64位明文打乱。
  • 进行16轮feistel函数后在进行逆初始运算

Python DES加密实现原理及实例解析

​ 以一组为例子来说明,一组明文8个字节,64位。有16轮迭代,要运行16次feistel函数。注意在16轮迭代前要把明文进行初始置换,迭代后把左右两边数据合并成64位再进行逆初始运算。

把64位明文左右对半分成两份。

右边的先进行部分进行扩展置换,32位变成48位。

再和对应轮数的子密钥进行异或运算。

再进行S盒运算,48位变成32位。S盒运算具体操作方法是,把48位数据分成8份,每份就有6位数据,比如010110,把头和尾结合位00,变成十进制就是0,中间四位的十进制为11,所以(x,y)为(0,11)

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

在上面这个表中表示的就是12,在把12变成2进制就是1100,所以6位就变成了4位。总共有8份数据,也有8个表。每份对应的运算的表都不一样。

再进行P盒运算。

最后和左边的32位进行异或运算。

解密

解密部分除了在feistel函数中调用子密钥的顺序相反外,其他都一样。加密调用的顺序是1-16,解密是16-1。

代码

#################################辅助函数######################################

# 十进制转成二进制
def INT_BIN(NUM):
  i = bin(NUM)[2:]
  if len(i) != 8:
    i = ((8 - len(i)) * '0') + i

  return i

# 置换函数
def Replace(ARR,change):
  ARR1 = []
  for i in ARR:
    a = ''
    for j in change:
      a += i[j-1]
    ARR1.append(a)
  return ARR1

# 异或运算
def XOR(a,b):
  c=""
  for i,j in zip(a,b):
    if i==j:
      c+='0'
    else:
      c+='1'
  return [c]

# 二进制转字符
def ASCII(A):
  text = ''
  for i in A:
    for j in range(8):
      b = i[j*8:(j+1)*8]
      text += chr(int(b,2))
  return text

##############################################################################

#################################密钥生成######################################
# 先PC1置换、将56位密钥对半分L0和R0、分别对L0和R0进行左循环移位,
# (当轮数为第1、2、9、16轮时,移动1位,其余时候移动两位)L0,R0移动1位
# 后得到L1,R1,L1+R0进行PC2置换得到密钥K1,L1和R0继续进行下一轮,直到生成16个子密钥

# PC-1置换表
PC1 = [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]

# PC-2置换表
PC2 = [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]

# 生成子密钥函数
def GenerateSubkey(Key):
  # 字符串转二进制
  K = ""
  i_byte = bytes(Key, encoding='utf-8')
  for i_bin in i_byte:
    K += INT_BIN(i_bin)

  # PC1置换
  ReplacePc1 = Replace([K],PC1)

  # 生成16组子密钥
  Lmi = []
  Rmi = []
  Lmi.append(ReplacePc1[0][:28])
  Rmi.append(ReplacePc1[0][28:])
  for i in range(1,17):
    if i in (1, 2, 9, 16):
      Lmi.append(Lmi[i-1][1:]+Lmi[i-1][:1])
      Rmi.append(Rmi[i-1][1:]+Rmi[i-1][:1])
    else:
      Lmi.append(Lmi[i-1][2:]+Lmi[i-1][:2])
      Rmi.append(Rmi[i-1][2:]+Rmi[i-1][:2])
  del Lmi[0]
  del Rmi[0]
  del ReplacePc1[0]
  for i in range(16):
    ReplacePc1.append(Lmi[i]+Rmi[i])

  # PC2置换
  return Replace(ReplacePc1,PC2)

###########################################################################

#################################明文处理###################################
# 明文填充,采用PKCS #5规则,如果刚好满足每组有8个字节,则再添加一组,每个字节为
# 000010000,如果最后一组没有8个字节,则把这一组填充成8个字节,填充的字节为少掉的
# 字节的数目,比如有7个字节,则填充00000001

# 对明文进行填充,分组
def InitPlaintext(Plaintext):
  DecimalList = []
  BytesList = []
  BinList = []
  
  # 字符串转成10机制
  i_byte = bytes(Plaintext, encoding='utf-8')
  for i_bin in i_byte:
    DecimalList.append(i_bin)

  # 刚好满足分组
  if len(DecimalList) % 8 == 0:
    for i in range(8):
      DecimalList.append(8)
    for i in range(int(len(DecimalList)/8)):
      BytesList.append(DecimalList[i*8:(i+1)*8])
  # 不满足分组
  else:
    INT = 8 - len(DecimalList) % 8
    for i in range(INT):
      DecimalList.append(INT)
    for i in range(int(len(DecimalList)/8)):
      BytesList.append(DecimalList[i*8:(i+1)*8])
  
  # 10进制转2进制
  for i in BytesList:
    TMP = ''
    for j in i:
      TMP += INT_BIN(j)
    BinList.append(TMP)
  
  return BinList

###########################################################################

################################feistel函数################################
#ip初始置换表
IPINIT = [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]

#扩展E置换表
EExten = [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盒置换表
PBOX = [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]

#逆初始置换表
P1 = [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]

#8个s盒
S_1 = [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_2 = [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_3 = [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_4 = [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_5 = [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_6 = [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_7 = [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_8 = [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_9 = []
S_9.append(S_1)
S_9.append(S_2)
S_9.append(S_3)
S_9.append(S_4)
S_9.append(S_5)
S_9.append(S_6)
S_9.append(S_7)
S_9.append(S_8)

# S盒置换
def S(R):
  s = ''
  for i in range(8):
    a = R[i*6:(i+1)*6]
    x = int(a[0]+a[-1],2)
    y = int(a[1:5],2)
    s += INT_BIN(S_9[i][x*15+y])[4:]
  return[s]


# feistel函数
def feistel(L, R, K):
  # 扩展置换
  Expand = Replace(R,EExten)
  # 异或运算
  Expand = XOR(Expand[0],K)
  # S盒运算
  Expand = S(Expand[0])
  # P盒
  Expand = Replace(Expand,PBOX)
  # 异或运算
  Expand = XOR(L[0],Expand[0])

  return Expand[0]

###########################################################################

################################加、解密函数################################
# 加密
def Encrypt(PlanText,Key):
  # 初始置换
  IP1 = Replace(InitPlaintext(PlanText),IPINIT)
  # 生成子密钥
  SubkeyList = GenerateSubkey(Key)

  # 16轮迭代
  Ciphertext = []
  for i in IP1:
    L = i[:32]
    R = i[32:]
    for k in SubkeyList:
      TMP = feistel([L],[R],k)
      L = R
      R = TMP
    # 逆初始置换
    Ciphertext.append(Replace([R+L],P1)[0])
  return Ciphertext,SubkeyList

# 解密
def Decrypt(Ciphertext,Key):
  # 初始置换
  IP1 = Replace(Ciphertext,IPINIT) 

  # 16轮迭代
  PlanText = []
  for i in IP1:
    L = i[:32]
    R = i[32:]
    for k in Key[::-1]:
      TMP = feistel([L],[R],k)
      L = R
      R = TMP
    # 逆初始置换
    PlanText.append(Replace([R+L],P1)[0])
  return PlanText

###########################################################################

if __name__ == "__main__":
  miwen,miyao = Encrypt('computer','networks')
  print(miwen)
  print(ASCII(Decrypt(miwen,miyao)))

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python基础教程之循环介绍
Aug 29 Python
在Python中操作时间之mktime()方法的使用教程
May 22 Python
Python简单实现安全开关文件的两种方式
Sep 19 Python
Python爬虫天气预报实例详解(小白入门)
Jan 24 Python
Python基于递归实现电话号码映射功能示例
Apr 13 Python
使用python读取csv文件快速插入数据库的实例
Jun 21 Python
Python实现的简单计算器功能详解
Aug 25 Python
Python实现登陆文件验证方法
Oct 06 Python
python实现计数排序与桶排序实例代码
Mar 28 Python
使用jupyter notebook将文件保存为Markdown,HTML等文件格式
Apr 14 Python
Python如何在循环内使用list.remove()
Jun 01 Python
Python日志模块logging用法
Jun 05 Python
python获取系统内存占用信息的实例方法
Jul 17 #Python
树莓派4B安装Tensorflow的方法步骤
Jul 16 #Python
深入了解Python enumerate和zip
Jul 16 #Python
详细分析Python collections工具库
Jul 16 #Python
带你学习Python如何实现回归树模型
Jul 16 #Python
MATLAB数学建模之画图汇总
Jul 16 #Python
浅析Python迭代器的高级用法
Jul 16 #Python
You might like
2个自定义的PHP in_array 函数,解决大量数据判断in_array的效率问题
2014/04/08 PHP
PHP中的use关键字概述
2014/07/23 PHP
ThinkPHP中关联查询实例
2014/12/02 PHP
将FCKeditor导入PHP+SMARTY的实现方法
2015/01/15 PHP
PHP四种排序算法实现及效率分析【冒泡排序,插入排序,选择排序和快速排序】
2018/04/27 PHP
使用TextRange获取输入框中光标的位
2006/10/14 Javascript
JS对HTML标签select的获取、添加、删除操作
2013/10/17 Javascript
jquery ajax实现下拉框三级无刷新联动,且保存保持选中值状态
2013/10/29 Javascript
探讨jQuery的ajax使用场景(c#)
2013/12/03 Javascript
extjs每个组件要设置唯一的ID否则会出错
2014/06/15 Javascript
jQuery实现的自适应焦点图效果完整实例
2016/08/24 Javascript
underscore之Collections_动力节点Java学院整理
2017/07/10 Javascript
Vue.js中组件中的slot实例详解
2017/07/17 Javascript
react-native使用react-navigation进行页面跳转导航的示例
2017/09/07 Javascript
浅谈vuex 闲置状态重置方案
2018/01/04 Javascript
解决淘宝cnpm 安装后cnpm不是内部或外部命令的问题
2018/05/17 Javascript
全面了解JavaScript的作用域链
2019/04/03 Javascript
ES6中的class是如何实现的(附Babel编译的ES5代码详解)
2019/05/17 Javascript
js生成1到100的随机数最简单的实现方法
2020/02/07 Javascript
vue前端和Django后端如何查询一定时间段内的数据
2021/02/28 Vue.js
[00:52]黑暗之门更新 新英雄孽主驾临DOTA2
2016/08/24 DOTA
[09:47]2018DOTA2亚洲邀请赛4.5SOLO赛 No[o]ne vs Sumail
2018/04/06 DOTA
python模拟新浪微博登陆功能(新浪微博爬虫)
2013/12/24 Python
Python程序设计入门(3)数组的使用
2014/06/16 Python
python对url格式解析的方法
2015/05/13 Python
简介Python的collections模块中defaultdict类型的用法
2016/07/07 Python
利用Tkinter和matplotlib两种方式画饼状图的实例
2017/11/06 Python
cookies应对python反爬虫知识点详解
2020/11/25 Python
mysql的最长数据库名,表名,字段名可以是多长
2014/04/21 面试题
公务员年总结的自我评价
2013/10/25 职场文书
处级干部考察材料
2014/12/24 职场文书
七一活动主持词
2015/06/29 职场文书
该怎么书写道歉信?
2019/07/03 职场文书
《雪域豹影》读后感:父爱的伟大
2019/12/23 职场文书
为什么 Nginx 比 Apache 更牛逼
2021/03/31 Servers
使用python+pygame开发消消乐游戏附完整源码
2021/06/10 Python