import subprocess
import os

def extract_rsa_pubkey_bin(rsa_key_path):
    # Run openssl to extract a DER-encoded SubjectPublicKeyInfo
    proc = subprocess.Popen(
        ["openssl", "rsa", "-pubin", "-in", rsa_key_path, "-pubout", "-outform", "DER"],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    der, err = proc.communicate()
    if proc.returncode != 0:
        print(f"openssl failed: {err.decode()}")
        return None

    # Parse DER (Manual implementation based on secureboot.cpp)
    def asn1_parse_length(d, off):
        b = d[off]
        off += 1
        if b < 0x80:
            return b, off
        n = b & 0x7f
        res = 0
        for _ in range(n):
            res = (res << 8) | d[off]
            off += 1
        return res, off

    i = 0
    # SEQUENCE
    if der[i] != 0x30: raise Exception("expected SEQUENCE")
    i += 1
    _, i = asn1_parse_length(der, i)
    
    # AlgorithmIdentifier
    if der[i] != 0x30: raise Exception("expected algo SEQUENCE")
    i += 1
    algo_len, i = asn1_parse_length(der, i)
    i += algo_len
    
    # BIT STRING
    if der[i] != 0x03: raise Exception("expected BIT STRING")
    i += 1
    _, i = asn1_parse_length(der, i)
    if der[i] != 0x00: raise Exception("expected 0 unused bits")
    i += 1
    
    # RSAPublicKey SEQUENCE { N, E }
    if der[i] != 0x30: raise Exception("expected RSAPublicKey SEQUENCE")
    i += 1
    _, i = asn1_parse_length(der, i)
    
    # INTEGER N
    if der[i] != 0x02: raise Exception("expected INTEGER N")
    i += 1
    n_len, i = asn1_parse_length(der, i)
    if der[i] == 0x00: # Strip sign byte
        i += 1
        n_len -= 1
    n_be = der[i:i+n_len]
    i += n_len
    
    # INTEGER E
    if der[i] != 0x02: raise Exception("expected INTEGER E")
    i += 1
    e_len, i = asn1_parse_length(der, i)
    e_be = der[i:i+e_len]
    
    # Format N (256 bytes, little-endian)
    n_le = n_be[::-1]
    n_le = n_le.ljust(256, b'\x00')
    
    # Format E (8 bytes, little-endian)
    e_le = e_be[::-1]
    e_le = e_le.ljust(8, b'\x00')
    
    return n_le + e_le

# Main
pem_path = "milkyos-httpboot-public.pem"
pubkey_bin = extract_rsa_pubkey_bin(pem_path)

if pubkey_bin:
    # Format as comma-separated hex for EEPROM config
    hex_string = ",".join([f"0x{b:02x}" for b in pubkey_bin])
    print("Add this to your EEPROM config:")
    print(f"PUBLIC_KEY={hex_string}")
else:
    print("Failed to extract public key.")
