2023-04-24 19:24:28 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
"""
|
|
|
|
A custom authentication hash function aswell as an automated extension attack for it.
|
|
|
|
|
|
|
|
Since this (auth) hash did not have a name before, I gave it the name 'authur1'
|
|
|
|
|
|
|
|
@author Christoph J. Scherr <software@cscherr.de>
|
|
|
|
@license MIT
|
|
|
|
@source: https://git.cscherr.de/PlexSheep/python-dhbw/src/branch/master/src/authur1.py
|
|
|
|
"""
|
|
|
|
import math
|
|
|
|
import argparse
|
|
|
|
|
2023-04-24 20:37:43 +02:00
|
|
|
# constants for authur1
|
|
|
|
SHIFT_LENGTH = 17
|
2023-04-24 21:19:25 +02:00
|
|
|
DEFINED_INITIAL = bytearray([0x52, 0x4f, 0x46, 0x4c])
|
|
|
|
PADDING = 0xff
|
2023-04-24 19:24:28 +02:00
|
|
|
|
2023-04-24 21:19:25 +02:00
|
|
|
# constants for Circular shifting
|
|
|
|
# constant value defined in limits.h, it's 8 (bit) on my machine, on yours probably too.
|
|
|
|
CHAR_BIT = 8
|
|
|
|
# python is being a dynamic dumbass, do a 32 bit shift ~ 4 byte
|
|
|
|
VALUE_SIZE = 4
|
2023-04-24 20:37:43 +02:00
|
|
|
|
|
|
|
"""
|
|
|
|
The rotations are tested agains a c implementation and seem to work fine.
|
|
|
|
"""
|
|
|
|
def rotl(value: int, count: int) -> int:
|
|
|
|
mask: int = CHAR_BIT * VALUE_SIZE - 1;
|
|
|
|
count &= mask;
|
|
|
|
return (value << count) | (value >> (-count & mask));
|
|
|
|
|
|
|
|
def rotr(value: int, count: int) -> int:
|
|
|
|
mask: int = CHAR_BIT * VALUE_SIZE - 1;
|
|
|
|
count &= mask;
|
|
|
|
return (value >> count) | (value << (-count & mask));
|
|
|
|
|
2023-04-24 21:19:25 +02:00
|
|
|
"""
|
|
|
|
Now for the actual implementation of authur1
|
|
|
|
"""
|
|
|
|
def inner_authur1(input: int) -> int:
|
|
|
|
# should really be 32 bit block
|
|
|
|
# python sucks for binary operations
|
|
|
|
# assert input.bit_length() == 32, "not a 32 bit int :("
|
|
|
|
output: int
|
2023-04-24 20:37:43 +02:00
|
|
|
|
2023-04-24 21:19:25 +02:00
|
|
|
output = input ^ (rotr(input, SHIFT_LENGTH))
|
2023-04-24 20:37:43 +02:00
|
|
|
|
|
|
|
return output
|
2023-04-24 19:24:28 +02:00
|
|
|
|
2023-04-24 21:19:25 +02:00
|
|
|
def authur1(input: bytearray) -> bytearray:
|
|
|
|
internal_buffer: bytearray = bytearray()
|
|
|
|
accumulator: bytearray = DEFINED_INITIAL
|
|
|
|
for in_byte in input:
|
|
|
|
if not len(internal_buffer) == 4:
|
|
|
|
internal_buffer.append(in_byte)
|
|
|
|
continue
|
|
|
|
# else
|
|
|
|
assert len(internal_buffer) == 4, "internal buffer of authur1 not 4 byte long"
|
|
|
|
accumulator = bytearray(
|
|
|
|
inner_authur1(
|
|
|
|
# accumulator
|
|
|
|
int.from_bytes(accumulator, byteorder='big', signed=False)
|
|
|
|
# XOR
|
|
|
|
^
|
|
|
|
# internal_buffer
|
|
|
|
int.from_bytes(internal_buffer, byteorder='big', signed=False)
|
|
|
|
)
|
|
|
|
.to_bytes(byteorder="big", signed=False)
|
|
|
|
)
|
|
|
|
# finished loading input bytes into the hash, fill with padding and do it one last time
|
|
|
|
while not len(internal_buffer) == 4:
|
|
|
|
internal_buffer.append(PADDING)
|
|
|
|
assert len(internal_buffer) == 4, "internal buffer of authur1 not 4 byte long"
|
|
|
|
# same as above, one last time
|
|
|
|
accumulator = bytearray(
|
|
|
|
inner_authur1(
|
|
|
|
# accumulator
|
|
|
|
int.from_bytes(accumulator, byteorder='big', signed=False)
|
|
|
|
# XOR
|
|
|
|
^
|
|
|
|
# internal_buffer
|
|
|
|
int.from_bytes(internal_buffer, byteorder='big', signed=False)
|
|
|
|
)
|
|
|
|
.to_bytes(byteorder="big", signed=False)
|
|
|
|
)
|
|
|
|
|
|
|
|
return accumulator
|
2023-04-24 19:24:28 +02:00
|
|
|
|
|
|
|
def main():
|
2023-04-24 21:19:25 +02:00
|
|
|
parser = argparse.ArgumentParser(prog="authur1 authentication hash", description='Implementation and attack for the custom authur1 hash')
|
|
|
|
parser.add_argument('--hash', type=str,
|
|
|
|
help='an input that should be hashed')
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
if args.hash:
|
|
|
|
my_bytes: bytearray = bytearray(str.encode(args.hash))
|
|
|
|
hashed = authur1(my_bytes)
|
|
|
|
print("hash for \"%s\" is:\n%s" % (args.hash, hashed.hex()))
|
|
|
|
parser.print_help()
|
2023-04-24 19:24:28 +02:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|