Tutorial ======== X.509 certificates are used to authenticate clients on servers. The most common use case is for webservers using HTTPS. Creating a Certificate Signing Request (CSR) -------------------------------------------- When obtaining a certificate from a certificate authority (CA), the usual workflow is: 1. You generate a private/public key pair. 2. You create a request for a certificate, which is signed by your key (to prove that you own that key). 3. You give your CSR to a CA (but *not* the private key). 4. The CA validates that you own the resource (e.g. domain) you want a certificate for. 5. The CA gives you a certificate, signed by them. Which identifies your public key, and the resource you are authenticated for. If you want to obtain a certificate from a typical commercial CA, here's how. First, you'll need to generate a private key, we'll generate an RSA key (these are the most common types of keys on the web right now): .. code-block:: pycon >>> from cryptography.hazmat.backends import default_backend >>> from cryptography.hazmat.primitives import serialization >>> from cryptography.hazmat.primitives.asymmetric import rsa >>> # Generate our key >>> key = rsa.generate_private_key( ... public_exponent=65537, ... key_size=2048, ... backend=default_backend() ... ) >>> # Write our key to disk for safe keeping >>> with open("path/to/store/key.pem") as f: ... f.write(key.private_bytes( ... encoding=serialization.Encoding.PEM, ... format=serialization.PrivateFormat.TraditionalOpenSSL, ... encryption_algorithm=serialization.BestAvailableEncryption(b"passphrase"), ... )) If you've already generated a key you can load it with :func:`~cryptography.hazmat.primitives.serialization.load_pem_public_key`. Next we need to generate a certificate signing request. A typical CSR contains a few details: * Information about our public key (including a signature of the entire body). * Information about who *we* are. * Information about what domains this certificate is for. .. code-block:: pycon >>> from cryptography import x509 >>> # Generate a CSR >>> csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([ ... # Provide various details about who we are. ... x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"), ... x509.NameAttribute(x509.OID_STATE_OR_PROVINCE_NAME, u"CA"), ... x509.NameAttribute(x509.OID_LOCALITY_NAME, u"San Francisco"), ... x509.NameAttribute(x509.OID_ORGANIZATION_NAME, u"My Company"), ... x509.NameAttribute(x509.COMMON_NAME, u"mysite.com"), ... ])).add_extension(x509.SubjectAlternativeName([ ... # Describe what sites we want this certificate for. ... x509.DNSName(u"mysite.com"), ... x509.DNSName(u"www.mysite.com"), ... x509.DNSName(u"subdomain.mysite.com"), ... # Sign the CSR with our private key. ... ])).sign(key, hashes.SHA256(), default_backend()) >>> # Write our CSR out to disk. >>> with open("path/to/csr.pem") as f: ... f.write(csr.public_bytes(serialization.Encoding.PEM)) Now we can give our CSR to a CA, who will give a certificate to us in return.