In this article we're going to see how to create a CSR (Certificate Signing Request) and an RSA private key with Python.
In order to accomplish our task, we need to gather the following information:
- Country code (e.g. US)
- State or province name (e.g. Virginia)
- Locality name (e.g. Richmond)
- Organization name (e.g. My Company)
- Common name (the domain name, e.g. example.com)
We can then write a function that creates the CSR together with the private key and returns them as human-readable strings.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives import serialization
def create_csr(attrs):
key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
country = attrs.get('country','')
state = attrs.get('state','')
locality = attrs.get('locality','')
organization = attrs.get('organization','')
common_name = attrs.get('common_name', '')
dns_name1 = common_name
dns_name2 = f'www.{common_name}'
csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
x509.NameAttribute(NameOID.COUNTRY_NAME, country),
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, state),
x509.NameAttribute(NameOID.LOCALITY_NAME, locality),
x509.NameAttribute(NameOID.ORGANIZATION_NAME, organization),
x509.NameAttribute(NameOID.COMMON_NAME, common_name)
])).add_extension(
x509.SubjectAlternativeName([
x509.DNSName(dns_name1),
x509.DNSName(dns_name2)
]),
critical=False,
).sign(key, hashes.SHA256())
return {'key': key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()).decode('utf-8'), 'csr': csr.public_bytes(
encoding=serialization.Encoding.PEM).decode('utf-8')}
In order to make sure that this will always work, check if the OpenSSL library is installed on your machine and is properly recognized by Python.