diff --git a/geki/calc_title_server_enc_key.py b/geki/calc_title_server_enc_key.py index 5f8bda4..e5fc768 100644 --- a/geki/calc_title_server_enc_key.py +++ b/geki/calc_title_server_enc_key.py @@ -5,6 +5,7 @@ # ] # /// import argparse +import string from hashlib import blake2b from pathlib import Path from typing import cast @@ -24,8 +25,27 @@ FILE_MAP = { "noise1": "IV", "noise2": "Endpoint salt", } +ASCII_EX_CHARACTERS = ( + string.digits + + ":;<>@" + + string.ascii_uppercase + + "[]^_`" + + string.ascii_lowercase +) + + +def to_ascii_ex(input: bytes): + output: list[int] = [] + + for b in input: + b = (b - 48) % len(ASCII_EX_CHARACTERS) + output.append(b) + + return bytes(output) + parser = argparse.ArgumentParser() +_ = parser.add_argument("--ascii-ex", action="store_true", help="Use ASCII Ex encoding (needed for version > 115)") _ = parser.add_argument("mu3_data_path", type=Path) _ = parser.add_argument("key_iv_digest_fixed", type=bytes.fromhex, nargs="?", default=KEY_IV_DIGEST_FIXED) @@ -54,4 +74,7 @@ with (cast(Path, args.mu3_data_path) / "resources.assets").open("rb") as f: elif data.m_Name == "noise2": key = key[:8] + if args.ascii_ex and data.m_Name in {"noise0", "noise1"}: + key = to_ascii_ex(key) + print(f"{FILE_MAP[data.m_Name]}: {key.hex()}")