def dsa_feistel(half_block, subkey): assert len(half_block) == 32 assert len(subkey) == 48 expansion_output = bittools.permute(half_block, EXPANSION) xor_output = bittools.xor(expansion_output, subkey) sbox_output = dsa_substitution_box(xor_output) permute_output = bittools.permute(sbox_output, PERMUTATION) log(" Feistel(Right Block, Subkey):"); log(" Expand(Right Block) =", bits_to_pretty(expansion_output)) log(" Expanded(...) XOR Subkey =", bits_to_pretty(xor_output, 6)) log(" S-Box(...) =", bits_to_pretty(sbox_output)) log(" Permutation(...) (output) =", bits_to_pretty(permute_output)) return permute_output
def dsa_feistel(half_block, subkey): assert len(half_block) == 32 assert len(subkey) == 48 expansion_output = bittools.permute(half_block, EXPANSION) xor_output = bittools.xor(expansion_output, subkey) sbox_output = dsa_substitution_box(xor_output) permute_output = bittools.permute(sbox_output, PERMUTATION) log(" Feistel(Right Block, Subkey):") log(" Expand(Right Block) =", bits_to_pretty(expansion_output)) log(" Expanded(...) XOR Subkey =", bits_to_pretty(xor_output, 6)) log(" S-Box(...) =", bits_to_pretty(sbox_output)) log(" Permutation(...) (output) =", bits_to_pretty(permute_output)) return permute_output
def dsa_encrypt(block, key, decrypt=False): nrounds = 16 assert len(block) == 64 assert len(key) == 64 if decrypt: log("Decrypting:", bits_to_pretty(block)) else: log("Encrypting:", bits_to_pretty(block)) # Generate subkeys subkeys = [] key_left = bittools.permute(key, PERMUTED_CHOICE_1_LEFT) key_right = bittools.permute(key, PERMUTED_CHOICE_1_RIGHT) assert len(key_left) == 28 assert len(key_right) == 28 log("Generating Subkeys:") log(" Initial Key =", bits_to_pretty(key)) log(" Permuting into Left and Right keys") log(" Left Half =", bits_to_pretty(key_left)) log(" Right Half =", bits_to_pretty(key_right)) for i in range(nrounds): shift_amount = KEY_SHIFT_AMOUNTS[i] bittools.left_shift(key_left, shift_amount) bittools.left_shift(key_right, shift_amount) subkey = bittools.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 =", bits_to_pretty(key_left)) log(" Right Half =", bits_to_pretty(key_right)) log(" Permuting Left and Right key into subkey") log(" Subkey =", bits_to_pretty(subkey)) # Apply subkeys in reverse order if decrypting log("") if decrypt: log("Reversing order of subkeys") subkeys = subkeys[::-1] # Initial Permutation block = bittools.permute(block, INITIAL_PERMUTATION) log("Initial Permutation:", bits_to_pretty(block)) log("") # Rounds left_block = block[0:32] right_block = block[32:] for i in range(nrounds): log("Round %s:" % i) log(" Input:") log(" Subkey =", bits_to_pretty(subkeys[i])) log(" Left Block =", bits_to_pretty(left_block)) log(" Right Block =", bits_to_pretty(right_block)) tmp = right_block fiestel_out = dsa_feistel(right_block, subkeys[i]) right_block = bittools.xor(left_block, fiestel_out) left_block = tmp log(" Output:") log(" Left Block = Left Block XOR Feistel(...)") log(" =", bits_to_pretty(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 = bittools.permute(right_block + left_block, FINAL_PERMUTATION) log("Result after all rounds = Left Block + Right Block") log(" =", bits_to_pretty(right_block + left_block)) log("After Final Permutation =", bits_to_pretty(encrypted)) log("") return encrypted
def dsa_encrypt(block, key, decrypt=False): nrounds = 16 assert len(block) == 64 assert len(key) == 64 if decrypt: log("Decrypting:", bits_to_pretty(block)) else: log("Encrypting:", bits_to_pretty(block)) # Generate subkeys subkeys = [] key_left = bittools.permute(key, PERMUTED_CHOICE_1_LEFT) key_right = bittools.permute(key, PERMUTED_CHOICE_1_RIGHT) assert len(key_left) == 28 assert len(key_right) == 28 log("Generating Subkeys:") log(" Initial Key =", bits_to_pretty(key)) log(" Permuting into Left and Right keys") log(" Left Half =", bits_to_pretty(key_left)) log(" Right Half =", bits_to_pretty(key_right)) for i in xrange(nrounds): shift_amount = KEY_SHIFT_AMOUNTS[i] bittools.left_shift(key_left, shift_amount) bittools.left_shift(key_right, shift_amount) subkey = bittools.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 =", bits_to_pretty(key_left)) log(" Right Half =", bits_to_pretty(key_right)) log(" Permuting Left and Right key into subkey") log(" Subkey =", bits_to_pretty(subkey)) # Apply subkeys in reverse order if decrypting log("") if decrypt: log("Reversing order of subkeys") subkeys = subkeys[::-1] # Initial Permutation block = bittools.permute(block, INITIAL_PERMUTATION) log("Initial Permutation:", bits_to_pretty(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 =", bits_to_pretty(subkeys[i])) log(" Left Block =", bits_to_pretty(left_block)) log(" Right Block =", bits_to_pretty(right_block)) tmp = right_block fiestel_out = dsa_feistel(right_block, subkeys[i]) right_block = bittools.xor(left_block, fiestel_out) left_block = tmp log(" Output:") log(" Left Block = Left Block XOR Feistel(...)") log(" =", bits_to_pretty(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 = bittools.permute(right_block + left_block, FINAL_PERMUTATION) log("Result after all rounds = Left Block + Right Block") log(" =", bits_to_pretty(right_block+left_block)) log("After Final Permutation =", bits_to_pretty(encrypted)) log("") return encrypted