authur1 idk what i did but changes
This commit is contained in:
parent
eafb1587d3
commit
6129b1f9e8
|
@ -82,7 +82,7 @@ def authur1(input: bytearray, verbose: bool = False) -> bytearray:
|
|||
|
||||
assert len(accumulator) == 4, "accumulator too long: %d bytes" % len(accumulator)
|
||||
if verbose:
|
||||
print("returning state: %s" % accumulator.hex())
|
||||
print("last internal state: %s" % accumulator.hex())
|
||||
# now Q the accumulator and return
|
||||
# if input = "" this step breaks things, just remove it.
|
||||
if len(input) != 0:
|
||||
|
@ -91,42 +91,34 @@ def authur1(input: bytearray, verbose: bool = False) -> bytearray:
|
|||
accumulator: bytearray = bytearray(accuint.to_bytes(4))
|
||||
return accumulator
|
||||
|
||||
def test():
|
||||
init: int = int.from_bytes(DEFINED_INITIAL)
|
||||
a: int = inner_authur1(init)
|
||||
b: int = inner_authur1(a)
|
||||
c: int = inner_authur1(b)
|
||||
assert a == 0xded7e2d2, "Q(S0) returns wrong value: %s" % hex(a)
|
||||
assert b == 0x1b725f7d, "Q(Q(S0)) returns wrong value: %s" % hex(b)
|
||||
assert c == 0xa5886999, "Q(Q(Q(S0))) returns wrong value: %s" % hex(c)
|
||||
|
||||
print("Q aka inner_authur1 passed the test")
|
||||
|
||||
ha: bytearray = authur1(bytearray(0))
|
||||
hb: bytearray = authur1(bytearray(b'A'))
|
||||
hc: bytearray = authur1(bytearray(b'AB'))
|
||||
hd: bytearray = authur1(bytearray(b'ABC'))
|
||||
he: bytearray = authur1(bytearray(b'ABCD'))
|
||||
hf: bytearray = authur1(bytearray(b'ABCDE'))
|
||||
assert int.from_bytes(ha) == 0xded7e2d2, "H(\"\") returns wrong value: %s" % ha.hex()
|
||||
assert int.from_bytes(hb) == 0x5d725f7f, "H(\"A\") returns wrong value: %s" % hb.hex()
|
||||
assert int.from_bytes(hc) == 0x5f3b5f7f, "H(\"AB\") returns wrong value: %s" % hc.hex()
|
||||
assert int.from_bytes(hd) == 0x5f39137f, "H(\"ABC\") returns wrong value: %s" % hd.hex()
|
||||
assert int.from_bytes(he) == 0x5f391128, "H(\"ABCD\") returns wrong value: %s" % he.hex()
|
||||
assert int.from_bytes(hf) == 0x2f69af58, "H(\"ABCDE\") returns wrong value: %s" % hf.hex()
|
||||
|
||||
print("H aka authur1 passed the test")
|
||||
|
||||
test_extension_attack()
|
||||
|
||||
print("All tests passed!")
|
||||
|
||||
def keyed_hash(message: bytearray, key: bytearray) -> bytearray:
|
||||
assert len(key) == 16, "key is not 16 Byte long: %s" % len(key)
|
||||
# prepend only
|
||||
input: bytearray = key + message
|
||||
mic: bytearray = authur1(input)
|
||||
return mic
|
||||
|
||||
def reverse_inner_authur1(output: int) -> int:
|
||||
assert output.bit_length() <= 32, "output length is <= 32: %d" % output.bit_length()
|
||||
|
||||
# plexcryptool.binary uses u32 for shifting
|
||||
#output: int = input ^ (binary.rotl32(input, SHIFT_LENGTH))
|
||||
# -> output ^ input = binary.rotl32(input, SHIFT_LENGTH)
|
||||
# -> input = binary.rotl32(input, SHIFT_LENGTH) ^ output
|
||||
input: int = output ^ (binary.rotr32(output, SHIFT_LENGTH))
|
||||
|
||||
assert False, "inner_authur1 can not be reversed!"
|
||||
assert input.bit_length() <= 32, "input length is <= 32: %d" % input.bit_length()
|
||||
|
||||
return input
|
||||
|
||||
def find_last_internal_state(mic: bytearray) -> bytearray:
|
||||
# reverse the mic to get the last internal state
|
||||
# TODO
|
||||
raise NotImplementedError("find last internal state is still TODO")
|
||||
|
||||
return mic
|
||||
|
||||
def extension_attack(valid_pairs: list):
|
||||
"""
|
||||
Extension attack against keyed hash of authur1
|
||||
|
@ -156,26 +148,66 @@ def extension_attack(valid_pairs: list):
|
|||
> Knowledge of the key is not necessary at all, yet valid forgeries can be
|
||||
> produced efficiently by the adversary
|
||||
|
||||
find a valid message that has the right length (length % 16 == 0)
|
||||
use any convenient message that has low length?
|
||||
fill it with padding?
|
||||
-> internal block length is 4 byte
|
||||
-> we don't have one given in the exercise
|
||||
reverse the last state before finalizing in the hash
|
||||
-> we have a valid internal state and can continue to append our own whatever to it?
|
||||
-> But the mic at the end should change, right?
|
||||
|
||||
(the exercise said the Key K has length 16, which is really handy, so i don't need to calculate for that.)
|
||||
(16 % 4 is 0)
|
||||
"""
|
||||
# find a valid message
|
||||
target_pair = None
|
||||
for msg, mic in valid_pairs:
|
||||
print("%s has length %s" % (msg, len(msg)))
|
||||
if len(msg) % 16 == 0:
|
||||
if len(msg) % 4 == 0:
|
||||
# we have a message of the right length!
|
||||
target_pair = (msg, mic)
|
||||
else:
|
||||
# for now, just use the first one?
|
||||
while len(msg) % 4 != 0:
|
||||
msg.append(PADDING)
|
||||
target_pair = (msg, mic)
|
||||
if target_pair is None:
|
||||
print("The given originals were not sufficient to perform an extension attack.\n"+
|
||||
"We need a message, which has a length that is a multiple of 16 (Bytes).")
|
||||
return
|
||||
print("Found a fitting target pair: %s" % target_pair)
|
||||
last_internal: bytearray = find_last_internal_state(target_pair[1])
|
||||
print("Found a fitting target pair: (%s,%s)" % target_pair)
|
||||
|
||||
def test():
|
||||
init: int = int.from_bytes(DEFINED_INITIAL)
|
||||
a: int = inner_authur1(init)
|
||||
b: int = inner_authur1(a)
|
||||
c: int = inner_authur1(b)
|
||||
assert a == 0xded7e2d2, "Q(S0) returns wrong value: %s" % hex(a)
|
||||
assert b == 0x1b725f7d, "Q(Q(S0)) returns wrong value: %s" % hex(b)
|
||||
assert c == 0xa5886999, "Q(Q(Q(S0))) returns wrong value: %s" % hex(c)
|
||||
|
||||
print("Q aka inner_authur1 passed the test")
|
||||
|
||||
ha: bytearray = authur1(bytearray(0))
|
||||
hb: bytearray = authur1(bytearray(b'A'))
|
||||
hc: bytearray = authur1(bytearray(b'AB'))
|
||||
hd: bytearray = authur1(bytearray(b'ABC'))
|
||||
he: bytearray = authur1(bytearray(b'ABCD'))
|
||||
hf: bytearray = authur1(bytearray(b'ABCDE'))
|
||||
assert int.from_bytes(ha) == 0xded7e2d2, "H(\"\") returns wrong value: %s" % ha.hex()
|
||||
assert int.from_bytes(hb) == 0x5d725f7f, "H(\"A\") returns wrong value: %s" % hb.hex()
|
||||
assert int.from_bytes(hc) == 0x5f3b5f7f, "H(\"AB\") returns wrong value: %s" % hc.hex()
|
||||
assert int.from_bytes(hd) == 0x5f39137f, "H(\"ABC\") returns wrong value: %s" % hd.hex()
|
||||
assert int.from_bytes(he) == 0x5f391128, "H(\"ABCD\") returns wrong value: %s" % he.hex()
|
||||
assert int.from_bytes(hf) == 0x2f69af58, "H(\"ABCDE\") returns wrong value: %s" % hf.hex()
|
||||
|
||||
print("H aka authur1 passed the test")
|
||||
|
||||
test_reverse_inner_authur1()
|
||||
test_extension_attack()
|
||||
|
||||
print("All tests passed!")
|
||||
|
||||
def test_extension_attack():
|
||||
"""
|
||||
|
@ -184,9 +216,17 @@ def test_extension_attack():
|
|||
# TODO
|
||||
raise(NotImplementedError("Extension attack is still TODO"))
|
||||
|
||||
def test_reverse_inner_authur1():
|
||||
a = 0x1337
|
||||
aq = inner_authur1(a)
|
||||
assert reverse_inner_authur1(aq) == a, "reverse_inner_authur1 does not work:\n%s\nis not\n%s" % (
|
||||
bin(a),
|
||||
bin(reverse_inner_authur1(a))
|
||||
)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(prog="authur1 authentication hash", description='Implementation and attack for the custom authur1 hash. Don\'t actually use this hash!')
|
||||
parser.add_argument('-i', '--hash', type=str,
|
||||
parser = argparse.ArgumentParser(prog="authur1", description='Implementation and attack for the custom authur1 hash. Don\'t actually use this hash!')
|
||||
parser.add_argument('-i', '--hash', type=str, metavar="MSG",
|
||||
help='an input that should be hashed')
|
||||
parser.add_argument('-k', '--key', type=str,
|
||||
help='an key that should be used with auth mode')
|
||||
|
@ -194,7 +234,7 @@ def main():
|
|||
help='perform tests')
|
||||
parser.add_argument('-v', '--verbose', action="store_true",
|
||||
help='print many things')
|
||||
parser.add_argument('-e', '--extension-attack', type=str,
|
||||
parser.add_argument('-e', '--extension-attack', metavar="ORIGINALS", type=str,
|
||||
help='perform an extension attack, this option requires known mics in the form: "msg1:deadbeed,msg2:abababab,msg3:ecbadf,..."')
|
||||
parser.add_argument('-a', '--auth', action="store_true",
|
||||
help='generate a message integrity code (mic), needs a value to be hashed. If no key is specified, a random key will be generated.')
|
||||
|
|
Loading…
Reference in New Issue