Last active
May 17, 2022 20:18
-
-
Save frereit/f3f9095e5c668e1eeecdf16adfd32e21 to your computer and use it in GitHub Desktop.
Aufgabe 5.4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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