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 02 Python
python实现定时播放mp3
Mar 29 Python
Python中splitlines()方法的使用简介
May 20 Python
python实现淘宝秒杀脚本
Jun 23 Python
对Pytorch中nn.ModuleList 和 nn.Sequential详解
Aug 18 Python
详解python statistics模块及函数用法
Oct 27 Python
基于h5py的使用及数据封装代码
Dec 26 Python
PyTorch中的Variable变量详解
Jan 07 Python
基于Python计算圆周率pi代码实例
Mar 25 Python
Opencv python 图片生成视频的方法示例
Nov 18 Python
python用字节处理文件实例讲解
Apr 13 Python
Python实现猜拳与猜数字游戏的方法详解
Apr 06 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
咖啡机如何保养和日常清洁?
2021/03/03 冲泡冲煮
php判断邮箱地址是否存在的方法
2016/02/13 PHP
理解Javascript_05_原型继承原理
2010/10/13 Javascript
javascript进行数组追加方法小结
2014/06/16 Javascript
jQuery实现拖拽页面元素并将其保存到cookie的方法
2016/06/12 Javascript
Javascript中indexOf()和lastIndexOf应用方法实例
2016/08/24 Javascript
微信 java 实现js-sdk 图片上传下载完整流程
2016/10/21 Javascript
JavaScript中object和Object的区别(详解)
2017/02/27 Javascript
Bootstrap实现的标签页内容切换显示效果示例
2017/05/25 Javascript
JS实现数组的增删改查操作示例
2018/08/29 Javascript
微信小程序下拉刷新PullDownRefresh的使用方法
2018/11/29 Javascript
Vue 利用指令实现禁止反复发送请求的两种方法
2019/09/15 Javascript
js实现坦克大战游戏
2020/02/24 Javascript
JavaScript如何实现图片处理与合成
2020/05/29 Javascript
React实现类似淘宝tab居中切换效果的示例代码
2020/06/02 Javascript
[52:15]2014 DOTA2国际邀请赛中国区预选赛5.21 HGT VS LGD-GAMING
2014/05/23 DOTA
python中使用OpenCV进行人脸检测的例子
2014/04/18 Python
python利用datetime模块计算时间差
2015/08/04 Python
python结合API实现即时天气信息
2016/01/19 Python
Python用户推荐系统曼哈顿算法实现完整代码
2017/12/01 Python
Python变量访问权限控制详解
2019/06/29 Python
pytorch模型存储的2种实现方法
2020/02/14 Python
澳大利亚女性快速时尚零售商:Ally Fashion
2018/04/25 全球购物
戴尔马来西亚官网:Dell Malaysia
2020/05/02 全球购物
行政前台岗位职责
2013/12/04 职场文书
经典婚礼主持词
2014/03/13 职场文书
工程质量承诺书
2014/03/27 职场文书
综合实践活动总结
2014/05/05 职场文书
宣传工作经验材料
2014/06/02 职场文书
医院我们的节日活动实施方案
2014/08/22 职场文书
公务员党员评议表自我鉴定
2014/09/14 职场文书
保洁员岗位职责
2015/02/04 职场文书
聊聊golang中多个defer的执行顺序
2021/05/08 Golang
安装配置mysql及Navicat prenium的详细流程
2021/06/10 MySQL
MySQL解决Navicat设置默认字符串时的报错问题
2022/06/16 MySQL
Python通用验证码识别OCR库ddddocr的安装使用教程
2022/07/07 Python