📄 pydes.py
字号:
if ch & (1 << i) != 0: result[pos] = 1 else: result[pos] = 0 pos += 1 i -= 1 return result def __BitList_to_String(self, data): """Turn the list of bits -> data, into a string""" result = [] pos = 0 c = 0 while pos < len(data): c += data[pos] << (7 - (pos % 8)) if (pos % 8) == 7: result.append(c) c = 0 pos += 1 if _pythonMajorVersion < 3: return ''.join([ chr(c) for c in result ]) else: return bytes(result) def __permutate(self, table, block): """Permutate this block with the specified table""" return list(map(lambda x: block[x], table)) # Transform the secret key, so that it is ready for data processing # Create the 16 subkeys, K[1] - K[16] def __create_sub_keys(self): """Create the 16 subkeys K[1] to K[16] from the given key""" key = self.__permutate(des.__pc1, self.__String_to_BitList(self.getKey())) i = 0 # Split into Left and Right sections self.L = key[:28] self.R = key[28:] while i < 16: j = 0 # Perform circular left shifts while j < des.__left_rotations[i]: self.L.append(self.L[0]) del self.L[0] self.R.append(self.R[0]) del self.R[0] j += 1 # Create one of the 16 subkeys through pc2 permutation self.Kn[i] = self.__permutate(des.__pc2, self.L + self.R) i += 1 # Main part of the encryption algorithm, the number cruncher :) def __des_crypt(self, block, crypt_type): """Crypt the block of data through DES bit-manipulation""" block = self.__permutate(des.__ip, block) self.L = block[:32] self.R = block[32:] # Encryption starts from Kn[1] through to Kn[16] if crypt_type == des.ENCRYPT: iteration = 0 iteration_adjustment = 1 # Decryption starts from Kn[16] down to Kn[1] else: iteration = 15 iteration_adjustment = -1 i = 0 while i < 16: # Make a copy of R[i-1], this will later become L[i] tempR = self.R[:] # Permutate R[i - 1] to start creating R[i] self.R = self.__permutate(des.__expansion_table, self.R) # Exclusive or R[i - 1] with K[i], create B[1] to B[8] whilst here self.R = list(map(lambda x, y: x ^ y, self.R, self.Kn[iteration])) B = [self.R[:6], self.R[6:12], self.R[12:18], self.R[18:24], self.R[24:30], self.R[30:36], self.R[36:42], self.R[42:]] # Optimization: Replaced below commented code with above #j = 0 #B = [] #while j < len(self.R): # self.R[j] = self.R[j] ^ self.Kn[iteration][j] # j += 1 # if j % 6 == 0: # B.append(self.R[j-6:j]) # Permutate B[1] to B[8] using the S-Boxes j = 0 Bn = [0] * 32 pos = 0 while j < 8: # Work out the offsets m = (B[j][0] << 1) + B[j][5] n = (B[j][1] << 3) + (B[j][2] << 2) + (B[j][3] << 1) + B[j][4] # Find the permutation value v = des.__sbox[j][(m << 4) + n] # Turn value into bits, add it to result: Bn Bn[pos] = (v & 8) >> 3 Bn[pos + 1] = (v & 4) >> 2 Bn[pos + 2] = (v & 2) >> 1 Bn[pos + 3] = v & 1 pos += 4 j += 1 # Permutate the concatination of B[1] to B[8] (Bn) self.R = self.__permutate(des.__p, Bn) # Xor with L[i - 1] self.R = list(map(lambda x, y: x ^ y, self.R, self.L)) # Optimization: This now replaces the below commented code #j = 0 #while j < len(self.R): # self.R[j] = self.R[j] ^ self.L[j] # j += 1 # L[i] becomes 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 24 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.setIV(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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -