#!/usr/bin/env python3 """Utility to retrieve Ed25519 signing public key for client configuration. This script outputs the public key in base64 format for adding to SignatureVerificationService.ts on the client side. Usage: python get_signing_key.py """ # Standard library imports import base64 import os import sys from typing import Tuple # Third-party imports from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization def get_signing_public_key() -> Tuple[str, str]: """Read signing public key from file. Returns: Tuple of (PEM format string, base64 encoded string). Raises: SystemExit: If key file not found or failed to load. """ key_file = os.getenv( "ED25519_SIGNING_KEY_PATH", "/app/secrets/ed25519_signing_key.pem" ) if not os.path.exists(key_file): print( f"ERROR: Signing key file not found: {key_file}", file=sys.stderr, ) print("", file=sys.stderr) print("SOLUTION:", file=sys.stderr) print( "1. Start the API server first to generate the key:", file=sys.stderr, ) print( " docker-compose up remote_access_api", file=sys.stderr, ) print( "2. Or run this script inside the container:", file=sys.stderr, ) print( " docker-compose exec remote_access_api python get_signing_key.py", file=sys.stderr, ) sys.exit(1) try: with open(key_file, "rb") as f: private_key_pem = f.read() private_key = serialization.load_pem_private_key( private_key_pem, password=None, backend=default_backend() ) public_key = private_key.public_key() public_key_pem = public_key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo, ) public_key_b64 = base64.b64encode(public_key_pem).decode("utf-8") return public_key_pem.decode("utf-8"), public_key_b64 except Exception as e: print( f"ERROR: Failed to load signing key: {e}", file=sys.stderr, ) sys.exit(1) def main() -> None: """Main function to display signing public key.""" print("=" * 80) print("Ed25519 Signing Public Key for Client Configuration") print("=" * 80) print("") pem, base64_encoded = get_signing_public_key() print("PEM Format:") print(pem) print("Base64 Encoded (for client configuration):") print(base64_encoded) print("") print("=" * 80) print("How to use:") print("=" * 80) print("") print("1. Copy the Base64 encoded key above") print("") print( "2. Update MachineControlCenter/src/renderer/services/SignatureVerificationService.ts:" ) print("") print(" const TRUSTED_SIGNING_KEYS: Record = {") print(f" production: '{base64_encoded}',") print(f" development: '{base64_encoded}',") print(f" local: '{base64_encoded}'") print(" };") print("") print("3. Rebuild the client application:") print(" cd MachineControlCenter") print(" npm run build") print("") print("=" * 80) print("") if __name__ == "__main__": main()