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

加密流程

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

密钥部分

明文部分

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

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)))

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持来客网。