from datetime import datetime, timedelta from ipaddress import ip_address from os import path from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec, rsa from cryptography.x509 import ( BasicConstraints, CertificateBuilder, DNSName, ExtendedKeyUsage, IPAddress, KeyUsage, Name, NameAttribute, SubjectAlternativeName, random_serial_number, ) from cryptography.x509.oid import ExtendedKeyUsageOID, NameOID def writefiles(key, cert): cn = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value folder = path.join(path.dirname(__file__), cn) with open(path.join(folder, "fullchain.pem"), "wb") as f: f.write(cert.public_bytes(serialization.Encoding.PEM)) with open(path.join(folder, "privkey.pem"), "wb") as f: f.write( key.private_bytes( serialization.Encoding.PEM, serialization.PrivateFormat.TraditionalOpenSSL, serialization.NoEncryption(), ) ) def selfsigned(key, common_name, san): subject = issuer = Name( [ NameAttribute(NameOID.COMMON_NAME, common_name), NameAttribute(NameOID.ORGANIZATION_NAME, "Sanic Org"), ] ) cert = ( CertificateBuilder() .subject_name(subject) .issuer_name(issuer) .public_key(key.public_key()) .serial_number(random_serial_number()) .not_valid_before(datetime.utcnow()) .not_valid_after(datetime.utcnow() + timedelta(days=365.25 * 8)) .add_extension( KeyUsage(True, False, False, False, False, False, False, False, False), critical=True, ) .add_extension( ExtendedKeyUsage( [ ExtendedKeyUsageOID.SERVER_AUTH, ExtendedKeyUsageOID.CLIENT_AUTH, ] ), critical=False, ) .add_extension( BasicConstraints(ca=True, path_length=None), critical=True, ) .add_extension( SubjectAlternativeName( [ IPAddress(ip_address(n)) if n[0].isdigit() or ":" in n else DNSName(n) for n in san ] ), critical=False, ) .sign(key, hashes.SHA256()) ) return cert # Sanic example/test self-signed cert RSA key = rsa.generate_private_key(public_exponent=65537, key_size=2048) cert = selfsigned( key, "sanic.example", [ "sanic.example", "www.sanic.example", "*.sanic.test", "2001:db8::541c", ], ) writefiles(key, cert) # Sanic localhost self-signed cert ECDSA key = ec.generate_private_key(ec.SECP256R1) cert = selfsigned( key, "localhost", [ "localhost", "127.0.0.1", "::1", ], ) writefiles(key, cert)