diff --git a/src-py/plexcryptool/scripts/oaep_rsa.py b/src-py/plexcryptool/scripts/oaep_rsa.py index 4964a67..09d9ff3 100755 --- a/src-py/plexcryptool/scripts/oaep_rsa.py +++ b/src-py/plexcryptool/scripts/oaep_rsa.py @@ -7,12 +7,46 @@ Perform RSA-OAEP @source: https://git.cscherr.de/PlexSheep/plexcryptool/src/branch/master/plexcryptool/trash-hash.py """ +import argparse import hashlib import random from math import floor # the given key in the assignment GIVEN_PUB_KEY = (0xAF5466C26A6B662AC98C06023501C9DF6036B065BD1F6804B1FC86307718DA4048211FD68A06917DE6F81DC018DCAF84B38AB77A6538BA2FE6664D3FB81E4A0886BBCDAB071AD6823FE20DF1CD67D33FB6CC5DA519F69B11F3D48534074A83F03A5A9545427720A30A27432E94970155A026572E358072023061AF65A2A18E85, 0x10001) +GIVEN_MASK_FOR_DB = bytearray.fromhex(""" +ea600669f6f16b3a2ad05d4b6d9b23911c8cc432fddd8d34a68d88af +3d787b7eebf6cd1b720812086758ce56e24ab819ccd8fb5eedb1cae9 +f6f895667d7f89d0454b828777ecabc040a649c8956e78ec1c721370 +663065cbc343deabad9eb6f2aceab6bfed5beb232cc55413bfffa06e +68627d7ec3ded5 +""") +GIVEN_DB = bytearray.fromhex(""" +00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000000000000000000000000 +00000000000000000000000000000000000001466f6f626172203132 +33343536373839 +""") +GIVEN_MASKED_DB = bytearray.fromhex(""" +ea600669f6f16b3a2ad05d4b6d9b23911c8cc432fddd8d34a68d88af +3d787b7eebf6cd1b720812086758ce56e24ab819ccd8fb5eedb1cae9 +f6f895667d7f89d0454b828777ecabc040a649c8956e78ec1c721370 +663065cbc343deabad9eb6f2aceab6bfed5bea6543aa3672cddf915c +5b564848f4e6ec +""") +GIVEN_MASK_FOR_SEED = bytearray.fromhex("713162084a4e0e6d ") +GIVEN_MASKED_SEED = bytearray.fromhex("db2040f6425bb082") +GIVEN_SEED = 0xaa1122fe0815beef +GIVEN_SEED_BYTES = bytearray.fromhex("aa1122fe0815beef") +GIVEN_MSG = bytearray.fromhex("466f6f62617220313233343536373839") +GIVEN_OAEP = bytearray.fromhex(""" +00db2040f6425bb082ea600669f6f16b3a2ad05d4b6d9b23911c8cc4 +32fddd8d34a68d88af3d787b7eebf6cd1b720812086758ce56e24ab8 +19ccd8fb5eedb1cae9f6f895667d7f89d0454b828777ecabc040a649 +c8956e78ec1c721370663065cbc343deabad9eb6f2aceab6bfed5bea +6543aa3672cddf915c5b564848f4e6ec +""") SEED_LENGTH = 8 # bytes @@ -60,80 +94,102 @@ def calclen(n: int) -> int: else: return floor(len) -def rsa_oaep_inner(seed: bytearray, block: bytearray) -> tuple[bytearray, bytearray]: +def rsa_oaep_inner(seed: bytearray, block: bytearray, verbose: bool) -> tuple[bytearray, bytearray]: """ inner function of rsa-oaep """ + assert type(seed) == bytearray mgf_seed = mgf1(seed, len(block)) - print("mgf1(seed):\n%s" % mgf_seed.hex()) masked_db = byte_xor(mgf_seed, block) - print("mgf1(seed) ^ block:\n%s" % masked_db.hex()) mask_seed = mgf1(masked_db, len(seed)) - print("mgf1(mgf1(seed) ^ block):\n%s" % mask_seed.hex()) masked_seed = byte_xor(seed, mask_seed) - print("mgf1(mgf1(seed) ^ block) ^ seed:\n%s" % masked_seed.hex()) + if verbose: + print("mgf1(seed):\n%s" % mgf_seed.hex()) + print("mgf1(seed) ^ block:\n%s" % masked_db.hex()) + print("mgf1(mgf1(seed) ^ block):\n%s" % mask_seed.hex()) + print("mgf1(mgf1(seed) ^ block) ^ seed:\n%s" % masked_seed.hex()) return (masked_seed, masked_db) def test_rsa_oaep_inner(): - seed: bytearray = bytearray.fromhex("aa1122fe0815beef") - db: bytearray = bytearray.fromhex(""" - 00000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000000001466f6f626172203132 - 33343536373839 - """) - print("seed:\n%s" % seed.hex()) - print("db:\n%s" % db.hex()) + result = rsa_oaep_inner(GIVEN_SEED_BYTES, GIVEN_DB, True) - result = rsa_oaep_inner(seed, db) - - GIVEN_MASK_FOR_DB = bytearray.fromhex(""" - ea600669f6f16b3a2ad05d4b6d9b23911c8cc432fddd8d34a68d88af - 3d787b7eebf6cd1b720812086758ce56e24ab819ccd8fb5eedb1cae9 - f6f895667d7f89d0454b828777ecabc040a649c8956e78ec1c721370 - 663065cbc343deabad9eb6f2aceab6bfed5beb232cc55413bfffa06e - 68627d7ec3ded5 - """) - GIVEN_MASKED_DB = bytearray.fromhex(""" - ea600669f6f16b3a2ad05d4b6d9b23911c8cc432fddd8d34a68d88af - 3d787b7eebf6cd1b720812086758ce56e24ab819ccd8fb5eedb1cae9 - f6f895667d7f89d0454b828777ecabc040a649c8956e78ec1c721370 - 663065cbc343deabad9eb6f2aceab6bfed5bea6543aa3672cddf915c - 5b564848f4e6ec - """) - GIVEN_MASK_FOR_SEED = bytearray.fromhex("713162084a4e0e6d ") - GIVEN_MASKED_SEED = bytearray.fromhex("db2040f6425bb082") assert result[0] == GIVEN_MASKED_SEED, "is\n%s\ninstead of\n%s" % (result[0].hex(), GIVEN_MASKED_SEED.hex()) assert result[1] == GIVEN_MASKED_DB, "is\n%s\ninstead of\n%s" % (result[1].hex(), GIVEN_MASKED_DB.hex()) -def rsa_oaep(ha: bytearray, m: bytearray): +def rsa_oaep(ha: bytearray, m: bytearray, verbose: bool, seed: int = random.randint(0, 2**64 - 1)): # generate a seed - seed = random.randint(0, 2**64 - 1) - seed = bytearray(seed.to_bytes(calclen(seed), 'big')) + assert calclen(seed) == 8, "seed is wrong length: %d" % calclen(seed) + l_seed: bytearray = bytearray(seed.to_bytes(calclen(seed), 'big')) # build the message block: bytearray = bytearray(0) assert len(block) == 0 + maxlen = calclen(GIVEN_PUB_KEY[0]) - 1 - len(l_seed) curlen = 0 curlen += len(ha) curlen += len(m) block += ha - block += bytearray(calclen(GIVEN_PUB_KEY[0]) - curlen) + block += bytearray(maxlen - curlen - 1) + block += bytearray(0x01.to_bytes()) block += m - assert len(block) == calclen(GIVEN_PUB_KEY[0]), "curlen:\n%s\nmodlen:\n%s" % (curlen, calclen(GIVEN_PUB_KEY[0])) - result = rsa_oaep_inner(seed, block) - print() - print(result[0].hex()) - print(result[1].hex()) - print() + assert len(block) == maxlen + if verbose: + print("block:\n%s" % block.hex()) + # in this case + assert block == GIVEN_DB, "is\n%s\ninstead of\n%s" % (block.hex(), GIVEN_DB.hex()) + assert type(l_seed) == bytearray + result = rsa_oaep_inner(seed=l_seed, block=block, verbose=verbose) + if verbose: + print() + print(result[0].hex()) + print(result[1].hex()) + print() return bytearray(1) + result[0] + result[1] +def test_rsa_oaep(): + r = rsa_oaep(bytearray(0), GIVEN_MSG, True, GIVEN_SEED) + assert r == GIVEN_OAEP + print(r) + + def main(): - ha = bytearray(0) - m = bytearray.fromhex("466f6f62617220313233343536373839") - r = rsa_oaep(ha, m) - print("final:\n%s" % r.hex()) + parser = argparse.ArgumentParser(prog="oaep-rsa", description='A hacky Implementation of rsa-oaep') + parser.add_argument('-m', '--message', type=str, metavar="MSG", + help='the message of the oaep') + parser.add_argument('-rs', '--random-seed', action="store_true", + help='a random seed') + parser.add_argument('-s', '--seed', type=int, + help='a custom seed') + parser.add_argument('-a', '--hashed-data', type=str, + help='append some auth hashed stuff') + parser.add_argument('-v', '--verbose', action="store_true", + help='append some auth hashed stuff') + parser.add_argument('-t', '--test', action="store_true", + help='perform tests') + args = parser.parse_args() + + if args.test: + test_rsa_oaep() + test_rsa_oaep_inner() + exit() + if args.hashed_data: + ha = bytearray.fromhex(args.hashed_data) + else: + ha = bytearray(0) + if args.message: + m = bytearray.fromhex(args.message) + else: + m = bytearray.fromhex("466f6f62617220313233343536373839") + if args.seed: + seed: int = args.seed + r = rsa_oaep(ha, m, args.verbose, seed) + elif args.random_seed: + seed = random.randint(0, 2**64 - 1) + r = rsa_oaep(ha, m, args.verbose, seed) + else: + seed = GIVEN_SEED + r = rsa_oaep(ha, m, args.verbose, seed) + print("result:\n%s" % r.hex()) if __name__ == "__main__": main()