Skip to content

Instantly share code, notes, and snippets.

@frereit
Last active May 17, 2022 20:18
Show Gist options
  • Save frereit/f3f9095e5c668e1eeecdf16adfd32e21 to your computer and use it in GitHub Desktop.
Save frereit/f3f9095e5c668e1eeecdf16adfd32e21 to your computer and use it in GitHub Desktop.
Aufgabe 5.4
def rev_nibble(nibble: int):
return ((nibble << 3) & 0x8) | ((nibble << 1) & 0x4) | ((nibble >> 1) & 0x2) | (nibble >> 3)
def feistel_function(halfblock: int, key: int, verbose=False) -> int:
log = print if verbose else lambda *args, **kwargs: None
sbox = [0x4, 0x3, 0x9, 0xa, 0xb, 0x2, 0xe, 0x1,
0xd, 0xc, 0x8, 0x6, 0x7, 0x5, 0x0, 0xf]
log(f"\t\tFeistel function: {halfblock=:04x} with {key=:04x}")
newblock = rev_nibble((halfblock >> 12) & 0xf) | rev_nibble(
halfblock & 0xf) << 12
newblock |= (sbox[(halfblock >> 8) & 0xf] << 8) | (sbox[(halfblock >> 4) & 0xf] << 4)
log(f"\t\tPermutated and S-boxed block: {newblock=:04x}")
res = newblock ^ key
log(f"\t\tXOR'd block: {res=:04x}")
return res
def round(block: int, key: int, verbose=False) -> int:
log = print if verbose else lambda *args, **kwargs: None
log(f"\tApplying round to {block=:08x} with {key=:04x}")
lower_block = block & 0xffff
upper_block = block >> 16
log(f"\tLower block: {lower_block=:04x}")
log(f"\tUpper block: {upper_block=:04x}")
xor_key = feistel_function(lower_block, key, verbose)
log(f"\tXOR key: {xor_key=:04x}")
res = (xor_key ^ upper_block) + (lower_block << 16)
log(f"\tResult: {res=:08x}")
return res
def encrypt(block: int, ksa: list = [0xdead, 0xc0ff, 0xee5a], verbose=False) -> int:
for roundkey in ksa:
block = round(block, roundkey, verbose)
return block
def decrypt(block: int, ksa: list = [0xdead, 0xc0ff, 0xee5a], verbose=False) -> int:
block = (block << 16) & 0xffff0000 | (block >> 16) & 0xffff # switch left and right half for decryption
block = encrypt(block, reversed(ksa), verbose)
block = (block << 16) & 0xffff0000 | (block >> 16) & 0xffff # need to switch back after "encryption" (= reverse decryption)
return block
def test():
import random
for _ in range(1_000):
block = random.randint(0, 0xffffffff)
ksa = [random.randint(0, 0xffff) for _ in range(3)]
assert decrypt(encrypt(block, ksa), ksa) == block
assert feistel_function(0x1234, 0x2345) == 0x0aed
assert feistel_function(0xabcd, 0xbeef) == 0x089a
assert feistel_function(0x9876, 0xfedc) == 0x93c5
assert encrypt(0x12345678, [0x1aa2, 0x2bb3, 0x3cc4]) == 0x4313e07a
assert decrypt(0x4313e07a, [0x1aa2, 0x2bb3, 0x3cc4]) == 0x12345678
def main():
print("ENCRYPTING 0xabcd0815")
print(f"{encrypt(0xabcd0815, verbose=True)=:08x}")
print("Making sure decryption works: ", end="")
print(f"{decrypt(encrypt(0xabcd0815))=:08x}")
print("DECRYPTING 0x12345678")
print(f"{decrypt(0x12345678, verbose=True)=:08x}")
print("Making sure encryption works: ", end="")
print(f"{encrypt(decrypt(0x12345678))=:08x}")
if __name__ == '__main__':
import time
now = time.perf_counter()
test()
print(f"Tests took {time.perf_counter() - now} seconds")
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment