def feistel_round(half_block, subkey): assert len(half_block) == 32 assert len(subkey) == 48 expansion_output = destools.permute(half_block, EXPANSION) xor_output = destools.xor(expansion_output, subkey) sbox_output = substituion_round(xor_output) permute_output = destools.permute(sbox_output, PERMUTATION) log(" Feistel(Right Block, Subkey):"); log(" Expand(Right Block)=", convert_bits_to_string(expansion_output)) log(" Expanded(...) XOR Subkey=", convert_bits_to_string(xor_output, 6)) log(" S-Box(...)=", convert_bits_to_string(sbox_output)) log(" Permutation(...) (output) =", convert_bits_to_string(permute_output)) return permute_output
def encrypt(block, key, decrypt=False): nrounds = 16 assert len(block) == 64 assert len(key) == 64 if decrypt: log("Decrypting text to plaintext:", convert_bits_to_string(block)) else: log("Encrypting plaintext to ciphertext:", convert_bits_to_string(block)) # Generate substitution keys subkeys = [] key_left = destools.permute(key, PERMUTED_CHOICE_1_LEFT) key_right = destools.permute(key, PERMUTED_CHOICE_1_RIGHT) assert len(key_left) == 28 assert len(key_right) == 28 log("Generating Subkeys:") log(" Initial Key =", convert_bits_to_string(key)) log(" Permuting into Left and Right keys") log(" Left Half =", convert_bits_to_string(key_left)) log(" Right Half =", convert_bits_to_string(key_right)) for i in xrange(nrounds): shift_amount = KEY_SHIFT_AMOUNTS[i] destools.left_shift(key_left, shift_amount) destools.left_shift(key_right, shift_amount) subkey = destools.permute(key_left + key_right, PERMUTED_CHOICE_2) subkeys.append(subkey) log("") log("Subkey %s:" % i) log(" Shifting key halves to the left by %s bits" % shift_amount) log(" Left Half =", convert_bits_to_string(key_left)) log(" Right Half =", convert_bits_to_string(key_right)) log(" Permuting Left and Right key into subkey") log(" Subkey =", convert_bits_to_string(subkey)) # Apply subkeys in reverse order if decrypting log("") if decrypt: log("Reversing order of subkeys") subkeys = subkeys[::-1] # Initial Permutation block = destools.permute(block, INITIAL_PERMUTATION) log("Initial Permutation:", convert_bits_to_string(block)) log("") # Rounds left_block = block[0:32] right_block = block[32:] for i in xrange(nrounds): log("Round %s:" % i) log(" Input:") log(" Subkey =", convert_bits_to_string(subkeys[i])) log(" Left Block =", convert_bits_to_string(left_block)) log(" Right Block =", convert_bits_to_string(right_block)) tmp = right_block fiestel_out = feistel_round(right_block, subkeys[i]) right_block = destools.xor(left_block, fiestel_out) left_block = tmp log(" Output:") log(" Left Block = Left Block XOR Feistel(...)") log(" =", convert_bits_to_string(right_block)) log(" Right Block (Unchanged)") if i == 15: log(" DO NOT SWITCH right and left block after the last round") else: log(" Left and Right blocks are switched and input into next round.") log("") # Final Permutation # right and left are switched here because the final round does not switch # them. Here we just switch them back. encrypted = destools.permute(right_block + left_block, FINAL_PERMUTATION) log("Result after all rounds = Left Block + Right Block") log(" =", convert_bits_to_string(right_block+left_block)) log("After Final Permutation =", convert_bits_to_string(encrypted)) log("") return encrypted