mirror of
https://github.com/izzy2lost/libultraship.git
synced 2026-10-26 11:44:27 -07:00
* Fully migrated event system into lus * Fixed tidy * Last tidy error * Added some more tidy stuff * Last pass of tidy stuff * Implemented dynamic module loading among o2r metadata * Cleanup some things and moved to built-in libtcc * Reverted CI dependencies * Trying to fix libtcc compilation * Another attempt at trying to fix this * Fixed GetPlatform error * Attempt at fixing cross-compilation for libtcc * Another attempt for ios this time * Disabled codesign on ios * Addressed tidy comments * Implemented keystore system for signature validation * Renamed some things to manifest * Fixed small compilation issue * More tidy fixes * Fully tested checksum and signature validations * Added a sign tool * Renamed missing function * Removed leftover * Fixed scripts not loading * Implemented LoadAll based on dependencies * Small fix so mods can load high resolution textures * Added line fixer so it says the real path * Fixed an issue related to f3d modding * Fixed tidy * Shifted some opcodes by one * Fixed weird rebase shenanigans * Moved to throw when loading untrusted scripts * Fixed tidy * Splitted compile and load for better info on ports * Fixed tidy again * Fixed wrong types on event system * Fixed returning an invalid id when sorting, implemented an internal id tracker among optimizing the sort when registering a new listener * Removed an unused queue * Moved HexToBytes into StringHelper and renamed KeystoreSystem to Keystore * Moved ScriptLoader data to be private * Replaced default license * Exported symbols on windows, added variables to set more things on libtcc and changed cmake to tell cmake to export a .lib * Fixed wrong macro * Fixed an error when generating .a files * Fixed tidy * Fixed more tidy * I hate tidy * Disabled readability-identifier-naming for original c extern * Fixed wrong define * Removed segmented guard because of false positives * Fixed validation to verify if address comes from a DLL * Fixed comment * Fixed bad cast * Fixed wrong cast again * Implemented script loading test * Fixed missing virtual function * Added prints to tests * Fix tests * Fixed Script System tests * Fixed last error and a better way to test ModInit and ModExit * Updated dependencies among adding a tool to generate a keypair * Added a key load based on user-prompt, trying to fix linux test and updated sign tool to add public_key * Applied formatting on script_test * Fixed StringHelper format * Added missing header * Updated test to be a ptr on status * Removed unnecessary stuff * Fully validated and fixed keystore saving and loading * Updated geenerate keys script * Fixed CompileAll * Addressed latest comments * Updated autogenerated keys script * Updated untrusted handler to expose key too * Added an small warning when not using ed25519 keys * Added missing python dependencies * Fixed tidy and updated actions * Another attempt at fixing windows builds * Removed search by listener validation because sometimes the same callback is used * Added an error handler just to avoid crashing the program * Added better errors for compiler * Splitted logs into better fitted spdlog calls * Kinda non-scope but i fixed a big performance issue on shaders * Added KeyOrigin to know if it comes from the game, from lus or from the user * Renamed from ScriptSystem to ScriptLoader * Implemented cleanup on context destroy * Finish some cleaning * Wrapped dll load code into an optional ifder * Fixed linux tests * Enabled dll loading in test * Inverted define * Populates initial key list * Moves keys to root of LUS --------- Co-authored-by: Kenix Whisperwind <kenixwhisperwind@gmail.com>
98 lines
3.8 KiB
Python
98 lines
3.8 KiB
Python
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import shutil
|
|
import sys
|
|
import tempfile
|
|
import zipfile
|
|
|
|
from cryptography.hazmat.primitives import serialization
|
|
from cryptography.hazmat.primitives.asymmetric import ed25519
|
|
|
|
def update_zip_manifest(zip_path: str, public_key_hex: str, checksum_hex: str, signature_hex: str):
|
|
manifest_data = {}
|
|
|
|
with zipfile.ZipFile(zip_path, 'r') as zin:
|
|
if "manifest.json" in zin.namelist():
|
|
try:
|
|
existing_manifest = zin.read("manifest.json").decode('utf-8')
|
|
manifest_data = json.loads(existing_manifest)
|
|
except json.JSONDecodeError:
|
|
print("Warning: Existing manifest.json is invalid JSON. Overwriting.")
|
|
|
|
manifest_data["checksum"] = checksum_hex
|
|
manifest_data["signature"] = signature_hex
|
|
manifest_data["public_key"] = public_key_hex
|
|
|
|
fd, temp_path = tempfile.mkstemp(suffix=".zip")
|
|
os.close(fd)
|
|
|
|
try:
|
|
with zipfile.ZipFile(zip_path, 'r') as zin:
|
|
with zipfile.ZipFile(temp_path, 'w', zipfile.ZIP_DEFLATED) as zout:
|
|
for item in zin.infolist():
|
|
if item.filename != "manifest.json":
|
|
zout.writestr(item, zin.read(item.filename))
|
|
new_manifest_bytes = json.dumps(manifest_data, indent=4).encode('utf-8')
|
|
zout.writestr("manifest.json", new_manifest_bytes)
|
|
shutil.move(temp_path, zip_path)
|
|
except Exception as e:
|
|
if os.path.exists(temp_path):
|
|
os.remove(temp_path)
|
|
raise e
|
|
|
|
def load_private_key(key_path: str, password: bytes = None):
|
|
try:
|
|
with open(key_path, "rb") as key_file:
|
|
private_key = serialization.load_pem_private_key(
|
|
key_file.read(),
|
|
password=password
|
|
)
|
|
if not isinstance(private_key, ed25519.Ed25519PrivateKey):
|
|
print(f"Error: The key at '{key_path}' is not an Ed25519 private key.")
|
|
sys.exit(1)
|
|
return private_key
|
|
except FileNotFoundError:
|
|
print(f"Error: Private key file not found at '{key_path}'")
|
|
sys.exit(1)
|
|
|
|
def calculate_o2r_checksum(zip_path) -> bytes:
|
|
hasher = hashlib.blake2b()
|
|
with zipfile.ZipFile(zip_path, 'r') as zf:
|
|
all_entries = zf.namelist()
|
|
filtered_files = [f for f in all_entries if not f.endswith('/') and f != 'manifest.json']
|
|
filtered_files.sort()
|
|
|
|
for file_name in filtered_files:
|
|
hasher.update(file_name.encode('utf-8'))
|
|
with zf.open(file_name) as f:
|
|
for chunk in iter(lambda: f.read(8192), b""):
|
|
hasher.update(chunk)
|
|
|
|
return hasher.digest()
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description="Sign a ZIP and inject into manifest.json.")
|
|
parser.add_argument("zip_file", help="Path to the target .zip file")
|
|
parser.add_argument("private_key", help="Path to the PEM private key")
|
|
parser.add_argument("-p", "--passphrase", help="Passphrase for the PEM file", default=None)
|
|
|
|
args = parser.parse_args()
|
|
print(f"Processing {args.zip_file}...")
|
|
|
|
raw_checksum = calculate_o2r_checksum(args.zip_file)
|
|
hex_checksum = raw_checksum.hex()
|
|
|
|
passphrase_bytes = args.passphrase.encode('utf-8') if args.passphrase else None
|
|
private_key = load_private_key(args.private_key, password=passphrase_bytes)
|
|
|
|
public_key_obj = private_key.public_key()
|
|
raw_public_key = public_key_obj.public_bytes(
|
|
encoding=serialization.Encoding.Raw,
|
|
format=serialization.PublicFormat.Raw
|
|
)
|
|
public_key_hex = raw_public_key.hex()
|
|
signature_str = private_key.sign(raw_checksum).hex()
|
|
update_zip_manifest(args.zip_file, public_key_hex, hex_checksum, signature_str)
|
|
print("[SUCCESS] Zip signed successfully.") |