当前位置:   article > 正文

DES对称加密及三重DES(3DES)_des3加密

des3加密

 一、DES

概述

DES算法全称为Data Encryption Standard,即数据加密算法,它是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三个:Key、Data、Mode。其中Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密或解密。

算法原理

DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位,其算法主要分为两步:

(1)初始置换

其功能是把输入的64位数据块按位重新组合,并把输出分为L0、R0两部分,每部分各长32位,其置换规则为将输入的第58位换到第一位,第50位换到第2位……依此类推,最后一位是原来的第7位。L0、R0则是换位输出后的两部分,L0是输出的左32位,R0是右32位,例:设置换前的输入值为D1D2D3……D64,则经过初始置换后的结果为:L0=D58D50……D8;R0=D57D49……D7。

(2)逆置换

经过16次迭代运算后,得到L16、R16,将此作为输入,进行逆置换,逆置换正好是初始置换的逆运算,由此即得到密文输出。

二、 两个密钥的三重DES

由于DES密钥只有56bit,易于遭受穷举时攻击。作为一种替代加密方案,Tuchman提出使用两个密钥的三重DES加密方法,并在1985年成为美国的一个商用加密标准。该方法使用两个密钥,执行三次DES算法,如图2所示。加密的过程是加密-解密-加密,解密的过程是解密-加密-解密。

采用两个密钥进行三重加密的好处有:①两个密钥合起来有效密钥长度有112bit,可以满足商业应用的需要,若采用总长为168bit的三个密钥,会产生不必要的开销。②加密时采用加密-解密-加密,而不是加密-加密-加密的形式,这样有效的实现了与现有DES系统的向后兼容问题。因为当K1=K2时,三重DES的效果就和原来的DES一样,有助于逐渐推广三重DES。③三重DES具有足够的安全性,目前还没有关于攻破三重DES的报道。

 什么是三重DES

三重DES是为了增加DES的强度,将DES重复3次所得到的一种密码算法,通常缩写为3DES。

二 三重DSE加密

明文经过三次DES处理才能变成最后的密文,由于DES密钥长度实质是56位,因此3DES的密钥长度就是56*3=168比特。

注意:三重DES的三次DES加密是(加密->解密->加密),而不是(加密->加密->加密),为什么这样设计呢?看看下面这张图就明白了。

如果三次DES加密的密钥都相同,前两次DES,相当于还原成了密文,这样看来,真正起作用的只是最后一次。这样做的好处是:三重DES对DES具备向下兼容性。

还有一种密码叫DES-EDE2,下面我们用图来描述这一种密码。

当然,只有三个密钥互不相等才是正宗的DES-EDE3。

三 三重DES解密

三重DES的解密过程和加密过程正好相反,是以密钥3、密钥2、密钥1的顺序执行解密->加密->解密的操作。

四 三重DES现状

尽管三重DES目前还被银行等机构使用,但其处理速度不高,除了特别重视向下兼容性的情况外,很少被用于新的用途。

pydes:
 

  1. #-*- coding: utf8 -*-
  2. #Initial permut matrix for the datas
  3. # IP initial permut
  4. PI = [58, 50, 42, 34, 26, 18, 10, 2,
  5. 60, 52, 44, 36, 28, 20, 12, 4,
  6. 62, 54, 46, 38, 30, 22, 14, 6,
  7. 64, 56, 48, 40, 32, 24, 16, 8,
  8. 57, 49, 41, 33, 25, 17, 9, 1,
  9. 59, 51, 43, 35, 27, 19, 11, 3,
  10. 61, 53, 45, 37, 29, 21, 13, 5,
  11. 63, 55, 47, 39, 31, 23, 15, 7]
  12. #Initial permut made on the key
  13. CP_1 = [57, 49, 41, 33, 25, 17, 9,
  14. 1, 58, 50, 42, 34, 26, 18,
  15. 10, 2, 59, 51, 43, 35, 27,
  16. 19, 11, 3, 60, 52, 44, 36,
  17. 63, 55, 47, 39, 31, 23, 15,
  18. 7, 62, 54, 46, 38, 30, 22,
  19. 14, 6, 61, 53, 45, 37, 29,
  20. 21, 13, 5, 28, 20, 12, 4]
  21. #Permut applied on shifted key to get Ki+1
  22. CP_2 = [14, 17, 11, 24, 1, 5, 3, 28,
  23. 15, 6, 21, 10, 23, 19, 12, 4,
  24. 26, 8, 16, 7, 27, 20, 13, 2,
  25. 41, 52, 31, 37, 47, 55, 30, 40,
  26. 51, 45, 33, 48, 44, 49, 39, 56,
  27. 34, 53, 46, 42, 50, 36, 29, 32]
  28. #Expand matrix to get a 48bits matrix of datas to apply the xor with Ki
  29. E = [32, 1, 2, 3, 4, 5,
  30. 4, 5, 6, 7, 8, 9,
  31. 8, 9, 10, 11, 12, 13,
  32. 12, 13, 14, 15, 16, 17,
  33. 16, 17, 18, 19, 20, 21,
  34. 20, 21, 22, 23, 24, 25,
  35. 24, 25, 26, 27, 28, 29,
  36. 28, 29, 30, 31, 32, 1]
  37. #SBOX
  38. S_BOX = [
  39. [[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7],
  40. [0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8],
  41. [4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0],
  42. [15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
  43. ],
  44. [[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10],
  45. [3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5],
  46. [0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15],
  47. [13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
  48. ],
  49. [[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8],
  50. [13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1],
  51. [13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7],
  52. [1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
  53. ],
  54. [[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15],
  55. [13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9],
  56. [10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4],
  57. [3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
  58. ],
  59. [[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9],
  60. [14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6],
  61. [4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14],
  62. [11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
  63. ],
  64. [[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11],
  65. [10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8],
  66. [9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6],
  67. [4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
  68. ],
  69. [[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1],
  70. [13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6],
  71. [1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2],
  72. [6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
  73. ],
  74. [[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7],
  75. [1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2],
  76. [7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8],
  77. [2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
  78. ]
  79. ]
  80. #Permut made after each SBox substitution for each round
  81. P = [16, 7, 20, 21, 29, 12, 28, 17,
  82. 1, 15, 23, 26, 5, 18, 31, 10,
  83. 2, 8, 24, 14, 32, 27, 3, 9,
  84. 19, 13, 30, 6, 22, 11, 4, 25]
  85. #Final permut for datas after the 16 rounds
  86. PI_1 = [40, 8, 48, 16, 56, 24, 64, 32,
  87. 39, 7, 47, 15, 55, 23, 63, 31,
  88. 38, 6, 46, 14, 54, 22, 62, 30,
  89. 37, 5, 45, 13, 53, 21, 61, 29,
  90. 36, 4, 44, 12, 52, 20, 60, 28,
  91. 35, 3, 43, 11, 51, 19, 59, 27,
  92. 34, 2, 42, 10, 50, 18, 58, 26,
  93. 33, 1, 41, 9, 49, 17, 57, 25]
  94. #Matrix that determine the shift for each round of keys
  95. SHIFT = [1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1]
  96. def string_to_bit_array(text):#Convert a string into a list of bits
  97. array = list()
  98. for char in text:
  99. binval = binvalue(char, 8)#Get the char value on one byte
  100. array.extend([int(x) for x in list(binval)]) #Add the bits to the final list
  101. return array
  102. def bit_string_to_array(bitText):
  103. array = list()
  104. for bit in bitText.replace(" ",""):
  105. array.append(int(bit))
  106. return array
  107. def bit_array_to_string(array): #Recreate the string from the bit array
  108. res = ''.join([chr(int(y,2)) for y in [''.join([str(x) for x in _bytes]) for _bytes in nsplit(array,8)]])
  109. return res
  110. # 根据ascil编码把字符转成对应的二进制
  111. def binvalue(val, bitsize): #Return the binary value as a string of the given size
  112. binval = bin(val)[2:] if isinstance(val, int) else bin(ord(val))[2:]
  113. if len(binval) > bitsize:
  114. raise ("binary value larger than the expected size")
  115. while len(binval) < bitsize:
  116. binval = "0"+binval #Add as many 0 as needed to get the wanted size
  117. return binval
  118. def nsplit(s, n):#Split a list into sublists of size "n"
  119. return [s[k:k+n] for k in range(0, len(s), n)]
  120. def showBits(s, n):#Split a list into sublists of size "n"
  121. return " ".join(["".join([str(i) for i in s[k:k+n]]) for k in range(0, len(s), n)])
  122. ENCRYPT=1
  123. DECRYPT=0
  124. class des():
  125. def __init__(self):
  126. self.password = None
  127. self.text = None
  128. self.keys = list()
  129. def run(self, key, text, action=ENCRYPT):
  130. self.password = key
  131. self.text = text
  132. # 产生所有子密钥
  133. self.generatekeys() #Generate all the keys
  134. result = list()
  135. block = self.text
  136. block = self.permut(block,PI)#Apply the initial permutation
  137. g, d = nsplit(block, 32) #g(LEFT), d(RIGHT)
  138. tmp = None
  139. for i in range(16): #Do the 16 rounds
  140. d_e = self.expand(d, E) #Expand d to match Ki size (48bits)
  141. if action == ENCRYPT:
  142. tmp = self.xor(self.keys[i], d_e)#If encrypt use Ki
  143. else:
  144. tmp = self.xor(self.keys[15-i], d_e)#If decrypt start by the last key
  145. tmp = self.substitute(tmp) #Method that will apply the SBOXes
  146. tmp = self.permut(tmp, P)
  147. tmp = self.xor(g, tmp) # tmp = f(Rn-1,Kn)
  148. g = d # Ln = Rn-1
  149. d = tmp # Rn = Ln-1 + f(Rn-1,Kn)
  150. print(f"L{i+1}:{showBits(g, 8)}")
  151. print(f"R{i + 1}:{showBits(d, 8)}")
  152. result += self.permut(d+g, PI_1) #Do the last permut and append the result to result
  153. final_res = "".join([str(i) for i in result])
  154. return final_res
  155. # if padding and action==DECRYPT:
  156. # return self.removePadding(final_res) #Remove the padding if decrypt and padding is true
  157. # else:
  158. # return final_res #Return the final string of data ciphered/deciphered
  159. def substitute(self, d_e):#Substitute bytes using SBOX
  160. subblocks = nsplit(d_e, 6)#Split bit array into sublist of 6 bits
  161. result = list()
  162. for i in range(len(subblocks)): #For all the sublists
  163. block = subblocks[i]
  164. row = int(str(block[0])+str(block[5]),2)#Get the row with the first and last bit
  165. column = int(''.join([str(x) for x in block[1:][:-1]]),2) #Column is the 2,3,4,5th bits
  166. val = S_BOX[i][row][column] #Take the value in the SBOX appropriated for the round (i)
  167. bin = binvalue(val, 4)#Convert the value to binary
  168. result += [int(x) for x in bin]#And append it to the resulting list
  169. return result
  170. # 置换
  171. def permut(self, block, table):#Permut the given block using the given table (so generic method)
  172. return [block[x-1] for x in table]
  173. # 扩展
  174. def expand(self, block, table):#Do the exact same thing than permut but for more clarity has been renamed
  175. return [block[x-1] for x in table]
  176. def xor(self, t1, t2):#Apply a xor and return the resulting list
  177. return [x^y for x,y in zip(t1,t2)]
  178. def generatekeys(self):#Algorithm that generates all the keys
  179. self.keys = []
  180. # 把密钥转成这个形式 00110100 11000010.....
  181. key = self.password
  182. key = self.permut(key, CP_1) #Apply the initial permut on the key
  183. g, d = nsplit(key, 28) #Split it in to (g->LEFT),(d->RIGHT)
  184. for i in range(16):#Apply the 16 rounds
  185. g, d = self.shift(g, d, SHIFT[i]) #Apply the shift associated with the round (not always 1)
  186. tmp = g + d #Merge them
  187. self.keys.append(self.permut(tmp, CP_2)) #Apply the permut to get the Ki
  188. def shift(self, g, d, n): #Shift a list of the given value
  189. return g[n:] + g[:n], d[n:] + d[:n]
  190. def addPadding(self):#Add padding to the datas using PKCS5 spec.
  191. pad_len = 8 - (len(self.text) % 8)
  192. self.text += pad_len * chr(pad_len)
  193. def removePadding(self, data):#Remove the padding of the plain text (it assume there is padding)
  194. pad_len = ord(data[-1])
  195. return data[:-pad_len]
  196. def encrypt(self, key, text):
  197. return self.run(key, text, ENCRYPT)
  198. def decrypt(self, key, text):
  199. return self.run(key, text, DECRYPT)
  200. if __name__ == '__main__':
  201. plain_text = bit_string_to_array("00000001 00100011 01000101 01100111 10001001 10101011 11001101 11101111")
  202. key = bit_string_to_array("00010011 00110100 01010111 01111001 10011011 10111100 11011111 11110001")
  203. d = des()
  204. r = d.encrypt(key,plain_text)
  205. print(r)
  206. # 测试cyberchef
  207. r = bit_string_to_array("01011010 11110101 00010101 10110000 01001011 11101111 01010010 01000001")
  208. r2 = d.decrypt(key,r)
  209. print("Ciphered: %r" % r)
  210. print("Deciphered: ", r2)
  211. # 07040502033636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636
  212. #
  213. # 6d6e6f68695c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c5c

  1. l = [1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0]
  2. def showBits(s, n):#Split a list into sublists of size "n"
  3. return " ".join(["".join([str(i) for i in s[k:k+n]]) for k in range(0, len(s), n)])
  4. print(showBits(l, 8))

CBC模式调用:

  1. from pyDes import des, CBC, PAD_PKCS5
  2. import binascii
  3. # 秘钥
  4. KEY = 'Codeoooo'
  5. def des_encrypt(s):
  6. """
  7. DES 加密
  8. :param s: 原始字符串
  9. :return: 加密后字符串,16进制
  10. """
  11. secret_key = KEY # 密码
  12. iv = secret_key # 偏移
  13. # secret_key:加密密钥,CBC:加密模式,iv:偏移, padmode:填充
  14. des_obj = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
  15. # 返回为字节
  16. secret_bytes = des_obj.encrypt(s, padmode=PAD_PKCS5)
  17. # 返回为16进制
  18. return bytes.decode(binascii.b2a_hex(secret_bytes))
  19. def des_descrypt(s):
  20. """
  21. DES 解密
  22. :param s: 加密后的字符串,16进制
  23. :return: 解密后的字符串
  24. """
  25. secret_key = KEY
  26. iv = secret_key
  27. des_obj = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
  28. decrypt_str = des_obj.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
  29. return bytes.decode(decrypt_str)
  30. print(des_encrypt('codeooo'))
  31. print(des_descrypt('4ff67fd9b661f01d'))

ECB模式调用:

  1. from pyDes import des, ECB, PAD_PKCS5
  2. import base64
  3. DES_SECRET_KEY = '12345678'
  4. data = 'codeooo'
  5. des_obj = des(DES_SECRET_KEY, ECB, DES_SECRET_KEY, padmode=PAD_PKCS5)
  6. secret_bytes = str(base64.b64encode(des_obj.encrypt(data)), encoding = 'utf-8')
  7. print(secret_bytes)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/381540
推荐阅读
相关标签
  

闽ICP备14008679号