def GetDESDecryptionKey(self, encryption_key): temp = FeistelRoundInfo(0) temp.KeyLeft = self.ProcessPermutation(encryption_key, self.pc1BoxLeft) temp.KeyRight = self.ProcessPermutation(encryption_key, self.pc1BoxRight) # Run it through 16 Feistel rounds for i in range(self.nRounds): temp.RoundNumber = i self.RotateKeyHalves(temp, True) return temp
def RunDESEncryption(self, input_bit_array, key_bit_array, output_file_handler, write_to_output_file = True): isEncryption = True roundInfo = FeistelRoundInfo(0) # Run the PC1 permutation on the key to select 56 bits of the 64 bits of the key roundInfo.KeyLeft = self.ProcessPermutation(key_bit_array, self.pc1BoxLeft) roundInfo.KeyRight = self.ProcessPermutation(key_bit_array, self.pc1BoxRight) # Run the Feistel rounds inputIndex = 0 while inputIndex < len(input_bit_array): # Get the DES input of the appropriate length roundInfo.DataInput = self.GetDESBlock(input_bit_array, inputIndex) inputIndex += self.expectedBlockLength # Run the initial permutation on the data permutedInputBitArray = self.ProcessPermutation(roundInfo.DataInput, self.initialPermutationBox) roundInfo.DataInput = permutedInputBitArray # Run 16 Feistel rounds for i in range(self.nRounds): if i > 0: roundInfo.DataInput = roundInfo.DataOutput roundInfo.RoundNumber = i roundInfo = self.ProcessFeistelRound(roundInfo.DataInput, roundInfo.KeyLeft, roundInfo.KeyRight, roundInfo.RoundNumber, isEncryption) # Run the final permutation of the data roundInfo.DataOutput = self.ProcessPermutation(roundInfo.DataOutput, self.finalPermutationBox) # Append to output file if appropriate if write_to_output_file == True: output_file_handler.write(roundInfo.DataOutput.ToBytes()) lastOutputBlock = roundInfo.DataOutput return lastOutputBlock
def ProcessReverseFeistelRound(self, input_block_bit_array, key_left_bit_array, key_right_bit_array, round_number): isEncryption = False # Create result FeistelRoundInfo roundResult = FeistelRoundInfo(0) roundResult.RoundNumber = round_number roundResult.DataInput = input_block_bit_array roundResult.DataOutput = MyBitArray() roundResult.KeyLeft = MyBitArray() roundResult.KeyLeft.extend(key_left_bit_array) roundResult.KeyRight = MyBitArray() roundResult.KeyRight.extend(key_right_bit_array) # Assign names to the halves of the data input for easy conceptualization # of reorganization originalMr = MyBitArray() # refers to original encryption Mr for the round newMr = MyBitArray() # refers to the mangled original encryption Mr # XOR'd with the original encryption Ml self.SplitBitArray(roundResult.DataInput, [originalMr, newMr]) # Generate the subkey for the round subkey = self.ProcessKeySchedule(roundResult, isEncryption) # Process Feistel Function mangledMr = self.FeistelFunction(originalMr, subkey) # Create the original Ml originalMl = newMr ^ mangledMr # Reconstruct the input of the parallel encryption round roundResult.DataOutput = MyBitArray() roundResult.DataOutput.FromBits(originalMl.bits) roundResult.DataOutput.extend(originalMr) return roundResult
def ProcessFeistelRound(self, input_block_bit_array, key_left_bit_array, key_right_bit_array, round_number, is_encryption): # Requires a 64 bit input if len(input_block_bit_array) != 64 or len(key_left_bit_array) != 28 or len(key_right_bit_array) != 28: raise ValueError("ProcessFeistelRound received data or keys of an inappropriate length.") # Create result FeistelRoundInfo roundResult = FeistelRoundInfo(0) roundResult.RoundNumber = round_number roundResult.DataInput = input_block_bit_array roundResult.DataOutput = MyBitArray() roundResult.KeyLeft = MyBitArray() roundResult.KeyLeft.extend(key_left_bit_array) roundResult.KeyRight = MyBitArray() roundResult.KeyRight.extend(key_right_bit_array) # Split the data into two halves, call them Ml and Mr Ml = MyBitArray() Mr = MyBitArray() self.SplitBitArray(roundResult.DataInput, [Ml, Mr]) # Generate the subkey for the round subkey = self.ProcessKeySchedule(roundResult, is_encryption) # Process Feistel Function mangledMr = self.FeistelFunction(Mr, subkey) # XOR with Ml newMr = mangledMr ^ Ml # Concatenate XOR result with original Mr roundResult.DataOutput.extend(Mr) roundResult.DataOutput.extend(newMr) return roundResult
def RunDESDecryption(self, input_bit_array, key_bit_array, output_file_handler, write_to_output_file = True, last_input_block = False): roundInfo = FeistelRoundInfo(0) roundInfo.KeyLeft = MyBitArray() roundInfo.KeyRight = MyBitArray() self.SplitBitArray(key_bit_array, [roundInfo.KeyLeft, roundInfo.KeyRight]) # Run the Feistel rounds inputIndex = 0 while inputIndex < len(input_bit_array): # Get the DES input of the appropriate length roundInfo.DataInput = self.GetDESBlock(input_bit_array, inputIndex) inputIndex += self.expectedBlockLength # Run the reverse of the final permutation on the data permutedInputBitArray = self.ProcessPermutation(roundInfo.DataInput, self.finalPermutationBox, True) roundInfo.DataInput = permutedInputBitArray # Run 16 Feistel rounds for i in range(self.nRounds): # Set feistel round info correctly if i > 0: roundInfo.DataInput = roundInfo.DataOutput roundInfo.RoundNumber = self.nRounds - i - 1 roundInfo = self.ProcessReverseFeistelRound(roundInfo.DataInput, roundInfo.KeyLeft, roundInfo.KeyRight, roundInfo.RoundNumber) # Run the reverse of the initial permutation of the data roundInfo.DataOutput = self.ProcessPermutation(roundInfo.DataOutput, self.initialPermutationBox, True) # If decrypting and this is the last block of data to decrypt, # search for and remove padding bytes at the end of the message. if last_input_block == True or (len(input_bit_array) > self.expectedBlockLength and inputIndex >= len(input_bit_array)): roundInfo.DataOutput = self.RemovePadding(roundInfo.DataOutput) # Append to output file if appropriate if write_to_output_file == True: output_file_handler.write(roundInfo.DataOutput.ToBytes()) lastOutputBlock = roundInfo.DataOutput return lastOutputBlock