"""Generate self-signed certificate for pairing UI (HTTPS on 8088).""" import tempfile from datetime import datetime, timedelta, timezone from pathlib import Path from cryptography import x509 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.x509.oid import NameOID def generate_self_signed_cert( cn: str = "orderpy-bridge", valid_days: int = 365, ) -> tuple[Path, Path]: """Write key and cert to temp files. Returns (key_path, cert_path).""" key = rsa.generate_private_key(public_exponent=65537, key_size=2048) subject = issuer = x509.Name([ x509.NameAttribute(NameOID.COMMON_NAME, cn), x509.NameAttribute(NameOID.ORGANIZATION_NAME, "OrderPy Bridge"), ]) now = datetime.now(timezone.utc) cert = ( x509.CertificateBuilder() .subject_name(subject) .issuer_name(issuer) .public_key(key.public_key()) .serial_number(x509.random_serial_number()) .not_valid_before(now) .not_valid_after(now + timedelta(days=valid_days)) .sign(key, hashes.SHA256()) ) tmp = Path(tempfile.mkdtemp(prefix="orderpy_bridge_ssl_")) key_path = tmp / "key.pem" cert_path = tmp / "cert.pem" key_path.write_bytes( key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) ) cert_path.write_bytes(cert.public_bytes(serialization.Encoding.PEM)) return key_path, cert_path