50 lines
2.0 KiB
Python
50 lines
2.0 KiB
Python
# generate_cert.py – pure-Python, no OpenSSL needed
|
||
from cryptography import x509
|
||
from cryptography.x509.oid import NameOID
|
||
from cryptography.hazmat.primitives import hashes, serialization
|
||
from cryptography.hazmat.primitives.asymmetric import rsa
|
||
from datetime import datetime, timedelta
|
||
from pathlib import Path
|
||
import socket
|
||
|
||
def make_cert(cert_dir: str = ".cert", cn: str = "SinumerikPythonClient", DEBUG_PRINT=False):
|
||
Path(cert_dir).mkdir(exist_ok=True)
|
||
key_file = Path(cert_dir) / "key.pem"
|
||
cert_file = Path(cert_dir) / "cert.der"
|
||
|
||
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
|
||
|
||
# *** THIS _must_ match what the client will announce later ***
|
||
hostname = socket.gethostname() # e.g. “WIN-PC-01”
|
||
app_uri = f"urn:{hostname}:{cn}" # e.g. “urn:WIN-PC-01:SinumerikPythonClient”
|
||
|
||
cert = (
|
||
x509.CertificateBuilder()
|
||
.subject_name(x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, cn)]))
|
||
.issuer_name(x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, cn)]))
|
||
.public_key(key.public_key())
|
||
.serial_number(x509.random_serial_number())
|
||
.not_valid_before(datetime.utcnow() - timedelta(minutes=1))
|
||
.not_valid_after(datetime.utcnow() + timedelta(days=365))
|
||
.add_extension( # ← embed the same URI here
|
||
x509.SubjectAlternativeName([x509.UniformResourceIdentifier(app_uri)]),
|
||
critical=False,
|
||
)
|
||
.sign(key, hashes.SHA256())
|
||
)
|
||
|
||
key_pem = key.private_bytes(
|
||
serialization.Encoding.PEM,
|
||
serialization.PrivateFormat.TraditionalOpenSSL,
|
||
serialization.NoEncryption(),
|
||
)
|
||
cert_der = cert.public_bytes(serialization.Encoding.DER)
|
||
|
||
key_file.write_bytes(key_pem)
|
||
cert_file.write_bytes(cert_der)
|
||
if DEBUG_PRINT:
|
||
print(f"Created:\n {key_file}\n {cert_file}\n URI = {app_uri}")
|
||
|
||
if __name__ == "__main__":
|
||
make_cert(DEBUG_PRINT=True)
|