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之再深点,更懂list
Sep 20 Python
python登陆asp网站页面的实现代码
Jan 14 Python
python函数形参用法实例分析
Aug 04 Python
利用Celery实现Django博客PV统计功能详解
May 08 Python
Python中的单继承与多继承实例分析
May 10 Python
在Python中通过getattr获取对象引用的方法
Jan 21 Python
Python检测数据类型的方法总结
May 20 Python
python实现复制文件到指定目录
Oct 16 Python
Python多线程及其基本使用方法实例分析
Oct 29 Python
将python包发布到PyPI和制作whl文件方式
Dec 25 Python
python openCV实现摄像头获取人脸图片
Aug 20 Python
Python集合的基础操作
Nov 01 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
一首老MP3,致敬WAR3经典
2021/03/08 魔兽争霸
IIS环境下快速安装、配置和调试PHP5.2.0
2006/12/17 PHP
通过缓存数据库结果提高PHP性能的原理介绍
2012/09/05 PHP
用PHP代码在网页上生成图片
2015/07/01 PHP
符合标准的js表单提交的代码
2007/09/13 Javascript
浅谈JavaScript函数参数的可修改性问题
2013/12/05 Javascript
JS将光标聚焦在文本最后的实现代码
2014/03/28 Javascript
基于jQuery实现动态数字展示效果
2015/08/12 Javascript
基于replaceChild制作简单的吞噬特效
2015/09/21 Javascript
js移动焦点到最后位置的简单方法
2016/11/25 Javascript
浅析Ajax语法
2016/12/05 Javascript
JS中绑定事件顺序(事件冒泡与事件捕获区别)
2017/01/24 Javascript
node.js中cluster的使用教程
2017/06/09 Javascript
微信小程序wx.getImageInfo()如何获取图片信息
2018/01/26 Javascript
解决Vue 项目打包后favicon无法正常显示的问题
2018/09/01 Javascript
微信小程序实现下拉框功能
2019/07/16 Javascript
JS中准确判断变量类型的方法
2020/06/01 Javascript
OpenLayers加载缩放控件使用方法详解
2020/09/25 Javascript
在webstorm中配置less的方法详解
2020/09/25 Javascript
Python将多个excel表格合并为一个表格
2021/02/22 Python
Python回文字符串及回文数字判定功能示例
2018/03/20 Python
基于python的socket实现单机五子棋到双人对战
2020/03/24 Python
django settings.py 配置文件及介绍
2019/07/15 Python
python字符串的index和find的区别详解
2020/06/20 Python
python statsmodel的使用
2020/12/21 Python
HTML5中meta属性的使用方法
2016/02/29 HTML / CSS
Mavi牛仔裤美国官网:土耳其著名牛仔品牌
2016/09/24 全球购物
全球500多个机场的接送服务:Suntransfers
2019/06/03 全球购物
英文版区域经理求职信
2013/10/23 职场文书
毕业生护理专业个人求职信范文
2014/01/04 职场文书
幼儿园六一主持词开场白
2015/05/28 职场文书
安全第一课观后感
2015/06/18 职场文书
公司开业致辞
2015/07/29 职场文书
机关单位2016年创先争优活动总结
2016/04/05 职场文书
2019年个人工作总结范文(3篇)
2019/08/27 职场文书
Python Numpy库的超详细教程
2022/04/06 Python