python实现的DES加密算法和3DES加密算法实例

时间:2021-05-22

本文实例讲述了python实现的DES加密算法和3DES加密算法。分享给大家供大家参考。具体实现方法如下:

############################################################################## Documentation ############################################################################### Author: Todd Whiteman# Date: 16th March, 2009# Verion: 2.0.0# License: Public Domain - free to do as you wish# Homepage: http://twhiteman.netfirms.com/des.html## This is a pure python implementation of the DES encryption algorithm.# It's pure python to avoid portability issues, since most DES # implementations are programmed in C (for performance reasons).## Triple DES class is also implemented, utilising the DES base. Triple DES# is either DES-EDE3 with a 24 byte key, or DES-EDE2 with a 16 byte key.## See the README.txt that should come with this python module for the# implementation methods used.## Thanks to:# * David Broadwell for ideas, comments and suggestions.# * Mario Wolff for pointing out and debugging some triple des CBC errors.# * Santiago Palladino for providing the PKCS5 padding technique.# * Shaya for correcting the PAD_PKCS5 triple des CBC errors.#"""A pure python implementation of the DES and TRIPLE DES encryption algorithms.Class initialization--------------------pyDes.des(key, [mode], [IV], [pad], [padmode])pyDes.triple_des(key, [mode], [IV], [pad], [padmode])key -> Bytes containing the encryption key. 8 bytes for DES, 16 or 24 bytes for Triple DESmode -> Optional argument for encryption type, can be either pyDes.ECB (Electronic Code Book) or pyDes.CBC (Cypher Block Chaining)IV -> Optional Initial Value bytes, must be supplied if using CBC mode. Length must be 8 bytes.pad -> Optional argument, set the pad character (PAD_NORMAL) to use during all encrypt/decrpt operations done with this instance.padmode -> Optional argument, set the padding mode (PAD_NORMAL or PAD_PKCS5) to use during all encrypt/decrpt operations done with this instance.I recommend to use PAD_PKCS5 padding, as then you never need to worry about anypadding issues, as the padding can be removed unambiguously upon decryptingdata that was encrypted using PAD_PKCS5 padmode.Common methods--------------encrypt(data, [pad], [padmode])decrypt(data, [pad], [padmode])data -> Bytes to be encrypted/decryptedpad -> Optional argument. Only when using padmode of PAD_NORMAL. For encryption, adds this characters to the end of the data block when data is not a multiple of 8 bytes. For decryption, will remove the trailing characters that match this pad character from the last 8 bytes of the unencrypted data block.padmode -> Optional argument, set the padding mode, must be one of PAD_NORMAL or PAD_PKCS5). Defaults to PAD_NORMAL.Example-------from pyDes import *data = "Please encrypt my data"k = des("DESCRYPT", CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)# For Python3, you'll need to use bytes, i.e.:# data = b"Please encrypt my data"# k = des(b"DESCRYPT", CBC, b"\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)d = k.encrypt(data)print "Encrypted: %r" % dprint "Decrypted: %r" % k.decrypt(d)assert k.decrypt(d, padmode=PAD_PKCS5) == dataSee the module source (pyDes.py) for more examples of use.You can also run the pyDes.py file without and arguments to see a simple test.Note: This code was not written for high-end systems needing a fast implementation, but rather a handy portable solution with small usage."""import sys# _pythonMajorVersion is used to handle Python2 and Python3 differences._pythonMajorVersion = sys.version_info[0]# Modes of crypting / cypheringECB = 0CBC = 1# Modes of paddingPAD_NORMAL = 1PAD_PKCS5 = 2# PAD_PKCS5: is a method that will unambiguously remove all padding# characters after decryption, when originally encrypted with# this padding mode.# For a good description of the PKCS5 padding technique, see:# http://es R[i - 1] self.L = tempR i += 1 iteration += iteration_adjustment # Final permutation of R[16]L[16] self.final = self.__permutate(des.__fp, self.R + self.L) return self.final # Data to be encrypted/decrypted def crypt(self, data, crypt_type): """Crypt the data in blocks, running it through des_crypt()""" # Error check the data if not data: return '' if len(data) % self.block_size != 0: if crypt_type == des.DECRYPT: # Decryption must work on 8 byte blocks raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.") if not self.getPadding(): raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n. Try setting the optional padding character") else: data += (self.block_size - (len(data) % self.block_size)) * self.getPadding() # print "Len of data: %f" % (len(data) / self.block_size) if self.getMode() == CBC: if self.getIV(): iv = self.__String_to_BitList(self.getIV()) else: raise ValueError("For CBC mode, you must supply the Initial Value (IV) for ciphering") # Split the data into blocks, crypting each one seperately i = 0 dict = {} result = [] #cached = 0 #lines = 0 while i < len(data): # Test code for caching encryption results #lines += 1 #if dict.has_key(data[i:i+8]): #print "Cached result for: %s" % data[i:i+8] # cached += 1 # result.append(dict[data[i:i+8]]) # i += 8 # continue block = self.__String_to_BitList(data[i:i+8]) # Xor with IV if using CBC mode if self.getMode() == CBC: if crypt_type == des.ENCRYPT: block = list(map(lambda x, y: x ^ y, block, iv)) #j = 0 #while j < len(block): # block[j] = block[j] ^ iv[j] # j += 1 processed_block = self.__des_crypt(block, crypt_type) if crypt_type == des.DECRYPT: processed_block = list(map(lambda x, y: x ^ y, processed_block, iv)) #j = 0 #while j < len(processed_block): # processed_block[j] = processed_block[j] ^ iv[j] # j += 1 iv = block else: iv = processed_block else: processed_block = self.__des_crypt(block, crypt_type) # Add the resulting crypted block to our list #d = self.__BitList_to_String(processed_block) #result.append(d) result.append(self.__BitList_to_String(processed_block)) #dict[data[i:i+8]] = d i += 8 # print "Lines: %d, cached: %d" % (lines, cached) # Return the full crypted string if _pythonMajorVersion < 3: return ''.join(result) else: return bytes.fromhex('').join(result) def encrypt(self, data, pad=None, padmode=None): """encrypt(data, [pad], [padmode]) -> bytes data : Bytes to be encrypted pad : Optional argument for encryption padding. Must only be one byte padmode : Optional argument for overriding the padding mode. The data must be a multiple of 8 bytes and will be encrypted with the already specified key. Data does not have to be a multiple of 8 bytes if the padding character is supplied, or the padmode is set to PAD_PKCS5, as bytes will then added to ensure the be padded data is a multiple of 8 bytes. """ data = self._guardAgainstUnicode(data) if pad is not None: pad = self._guardAgainstUnicode(pad) data = self._padData(data, pad, padmode) return self.crypt(data, des.ENCRYPT) def decrypt(self, data, pad=None, padmode=None): """decrypt(data, [pad], [padmode]) -> bytes data : Bytes to be encrypted pad : Optional argument for decryption padding. Must only be one byte padmode : Optional argument for overriding the padding mode. The data must be a multiple of 8 bytes and will be decrypted with the already specified key. In PAD_NORMAL mode, if the optional padding character is supplied, then the un-encrypted data will have the padding characters removed from the end of the bytes. This pad removal only occurs on the last 8 bytes of the data (last data block). In PAD_PKCS5 mode, the special padding end markers will be removed from the data after decrypting. """ data = self._guardAgainstUnicode(data) if pad is not None: pad = self._guardAgainstUnicode(pad) data = self.crypt(data, des.DECRYPT) return self._unpadData(data, pad, padmode)############################################################################## Triple DES ##############################################################################class triple_des(_baseDes): """Triple DES encryption/decrytpion class This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or the DES-EDE2 (when a 16 byte key is supplied) encryption methods. Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes. pyDes.des(key, [mode], [IV]) key -> Bytes containing the encryption key, must be either 16 or bytes long mode -> Optional argument for encryption type, can be either pyDes.ECB (Electronic Code Book), pyDes.CBC (Cypher Block Chaining) IV -> Optional Initial Value bytes, must be supplied if using CBC mode. Must be 8 bytes in length. pad -> Optional argument, set the pad character (PAD_NORMAL) to use during all encrypt/decrpt operations done with this instance. padmode -> Optional argument, set the padding mode (PAD_NORMAL or PAD_PKCS5) to use during all encrypt/decrpt operations done with this instance. """ def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL): _baseDes.__init__(self, mode, IV, pad, padmode) self.setKey(key) def setKey(self, key): """Will set the crypting key for this object. Either 16 or 24 bytes long.""" self.key_size = 24 # Use DES-EDE3 mode if len(key) != self.key_size: if len(key) == 16: # Use DES-EDE2 mode self.key_size = 16 else: raise ValueError("Invalid triple DES key size. Key must be either 16 or 24 bytes long") if self.getMode() == CBC: if not self.getIV(): # Use the first 8 bytes of the key self._iv = key[:self.block_size] if len(self.getIV()) != self.block_size: raise ValueError("Invalid IV, must be 8 bytes in length") self.__key1 = des(key[:8], self._mode, self._iv, self._padding, self._padmode) self.__key2 = des(key[8:16], self._mode, self._iv, self._padding, self._padmode) if self.key_size == 16: self.__key3 = self.__key1 else: self.__key3 = des(key[16:], self._mode, self._iv, self._padding, self._padmode) _baseDes.setKey(self, key) # Override setter methods to work on all 3 keys. def setMode(self, mode): """Sets the type of crypting mode, pyDes.ECB or pyDes.CBC""" _baseDes.setMode(self, mode) for key in (self.__key1, self.__key2, self.__key3): key.setMode(mode) def setPadding(self, pad): """setPadding() -> bytes of length 1. Padding character.""" _baseDes.setPadding(self, pad) for key in (self.__key1, self.__key2, self.__key3): key.setPadding(pad) def setPadMode(self, mode): """Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5""" _baseDes.setPadMode(self, mode) for key in (self.__key1, self.__key2, self.__key3): key.setPadMode(mode) def setIV(self, IV): """Will set the Initial Value, used in conjunction with CBC mode""" _baseDes.setIV(self, IV) for key in (self.__key1, self.__key2, self.__key3): key.setIV(IV) def encrypt(self, data, pad=None, padmode=None): """encrypt(data, [pad], [padmode]) -> bytes data : bytes to be encrypted pad : Optional argument for encryption padding. Must only be one byte padmode : Optional argument for overriding the padding mode. The data must be a multiple of 8 bytes and will be encrypted with the already specified key. Data does not have to be a multiple of 8 bytes if the padding character is supplied, or the padmode is set to PAD_PKCS5, as bytes will then added to ensure the be padded data is a multiple of 8 bytes. """ ENCRYPT = des.ENCRYPT DECRYPT = des.DECRYPT data = self._guardAgainstUnicode(data) if pad is not None: pad = self._guardAgainstUnicode(pad) # Pad the data accordingly. data = self._padData(data, pad, padmode) if self.getMode() == CBC: self.__key1.setIV(self.getIV()) self.__key2.setIV(self.getIV()) self.__key3.setIV(self.getIV()) i = 0 result = [] while i < len(data): block = self.__key1.crypt(data[i:i+8], ENCRYPT) block = self.__key2.crypt(block, DECRYPT) block = self.__key3.crypt(block, ENCRYPT) self.__key1.setIV(block) self.__key2.setIV(block) self.__key3.setIV(block) result.append(block) i += 8 if _pythonMajorVersion < 3: return ''.join(result) else: return bytes.fromhex('').join(result) else: data = self.__key1.crypt(data, ENCRYPT) data = self.__key2.crypt(data, DECRYPT) return self.__key3.crypt(data, ENCRYPT) def decrypt(self, data, pad=None, padmode=None): """decrypt(data, [pad], [padmode]) -> bytes data : bytes to be encrypted pad : Optional argument for decryption padding. Must only be one byte padmode : Optional argument for overriding the padding mode. The data must be a multiple of 8 bytes and will be decrypted with the already specified key. In PAD_NORMAL mode, if the optional padding character is supplied, then the un-encrypted data will have the padding characters removed from the end of the bytes. This pad removal only occurs on the last 8 bytes of the data (last data block). In PAD_PKCS5 mode, the special padding end markers will be removed from the data after decrypting, no pad character is required for PAD_PKCS5. """ ENCRYPT = des.ENCRYPT DECRYPT = des.DECRYPT data = self._guardAgainstUnicode(data) if pad is not None: pad = self._guardAgainstUnicode(pad) if self.getMode() == CBC: self.__key1.setIV(self.getIV()) self.__key2.setIV(self.getIV()) self.__key3.setIV(self.getIV()) i = 0 result = [] while i < len(data): iv = data[i:i+8] block = self.__key3.crypt(iv, DECRYPT) block = self.__key2.crypt(block, ENCRYPT) block = self.__key1.crypt(block, DECRYPT) self.__key1.setIV(iv) self.__key2.setIV(iv) self.__key3.setIV(iv) result.append(block) i += 8 if _pythonMajorVersion < 3: data = ''.join(result) else: data = bytes.fromhex('').join(result) else: data = self.__key3.crypt(data, DECRYPT) data = self.__key2.crypt(data, ENCRYPT) data = self.__key1.crypt(data, DECRYPT) return self._unpadData(data, pad, padmode)

希望本文所述对大家的Python程序设计有所帮助。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章