blob: 4caa90b59e3de805ce32725c648d5f428b2ce0af [file] [log] [blame]
Alex Gaynor11b00cd2015-07-13 21:12:39 -04001Tutorial
2========
3
4X.509 certificates are used to authenticate clients on servers. The most common
Alex Gaynor0c91ddc2015-07-13 21:15:03 -04005use case is for web servers using HTTPS.
Alex Gaynor11b00cd2015-07-13 21:12:39 -04006
7Creating a Certificate Signing Request (CSR)
8--------------------------------------------
9
10When obtaining a certificate from a certificate authority (CA), the usual
Alex Gaynor0c91ddc2015-07-13 21:15:03 -040011flow is:
Alex Gaynor11b00cd2015-07-13 21:12:39 -040012
131. You generate a private/public key pair.
Alex Gaynor5bcd8e82015-07-13 21:17:31 -0400142. You create a request for a certificate, which is signed by your key (to
15 prove that you own that key).
Alex Gaynor11b00cd2015-07-13 21:12:39 -0400163. You give your CSR to a CA (but *not* the private key).
174. The CA validates that you own the resource (e.g. domain) you want a
18 certificate for.
Alex Gaynor5bcd8e82015-07-13 21:17:31 -0400195. The CA gives you a certificate, signed by them, which identifies your public
Alex Gaynor11b00cd2015-07-13 21:12:39 -040020 key, and the resource you are authenticated for.
Alex Gaynor5bcd8e82015-07-13 21:17:31 -0400216. You configure your server to use that certificate, combined with your
22 private key, to server traffic.
Alex Gaynor11b00cd2015-07-13 21:12:39 -040023
24If you want to obtain a certificate from a typical commercial CA, here's how.
25First, you'll need to generate a private key, we'll generate an RSA key (these
26are the most common types of keys on the web right now):
27
28.. code-block:: pycon
29
30 >>> from cryptography.hazmat.backends import default_backend
31 >>> from cryptography.hazmat.primitives import serialization
32 >>> from cryptography.hazmat.primitives.asymmetric import rsa
33 >>> # Generate our key
34 >>> key = rsa.generate_private_key(
35 ... public_exponent=65537,
36 ... key_size=2048,
37 ... backend=default_backend()
38 ... )
39 >>> # Write our key to disk for safe keeping
Alex Gaynor46c3e702015-08-12 14:52:56 -040040 >>> with open("path/to/store/key.pem", "w") as f:
Alex Gaynor11b00cd2015-07-13 21:12:39 -040041 ... f.write(key.private_bytes(
42 ... encoding=serialization.Encoding.PEM,
43 ... format=serialization.PrivateFormat.TraditionalOpenSSL,
44 ... encryption_algorithm=serialization.BestAvailableEncryption(b"passphrase"),
Alex Gaynord02bc122015-07-13 21:18:56 -040045 ... ))
Alex Gaynor11b00cd2015-07-13 21:12:39 -040046
47If you've already generated a key you can load it with
Alex Gaynor9ca48512015-07-16 07:03:40 -040048:func:`~cryptography.hazmat.primitives.serialization.load_pem_private_key`.
Alex Gaynor11b00cd2015-07-13 21:12:39 -040049
Alex Gaynor5bcd8e82015-07-13 21:17:31 -040050Next we need to generate a certificate signing request. A typical CSR contains
51a few details:
Alex Gaynor11b00cd2015-07-13 21:12:39 -040052
53* Information about our public key (including a signature of the entire body).
54* Information about who *we* are.
55* Information about what domains this certificate is for.
56
57.. code-block:: pycon
58
59 >>> from cryptography import x509
Paul Kehrer246daf72015-08-10 21:12:24 -050060 >>> from cryptography.x509.oid import NameOID
Alex Gaynor11b00cd2015-07-13 21:12:39 -040061 >>> # Generate a CSR
62 >>> csr = x509.CertificateSigningRequestBuilder().subject_name(x509.Name([
63 ... # Provide various details about who we are.
Paul Kehrer246daf72015-08-10 21:12:24 -050064 ... x509.NameAttribute(NameOID.COUNTRY_NAME, u"US"),
65 ... x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, u"CA"),
66 ... x509.NameAttribute(NameOID.LOCALITY_NAME, u"San Francisco"),
67 ... x509.NameAttribute(NameOID.ORGANIZATION_NAME, u"My Company"),
68 ... x509.NameAttribute(NameOID.COMMON_NAME, u"mysite.com"),
Alex Gaynor11b00cd2015-07-13 21:12:39 -040069 ... ])).add_extension(x509.SubjectAlternativeName([
70 ... # Describe what sites we want this certificate for.
71 ... x509.DNSName(u"mysite.com"),
72 ... x509.DNSName(u"www.mysite.com"),
73 ... x509.DNSName(u"subdomain.mysite.com"),
74 ... # Sign the CSR with our private key.
75 ... ])).sign(key, hashes.SHA256(), default_backend())
76 >>> # Write our CSR out to disk.
Alex Gaynor46c3e702015-08-12 14:52:56 -040077 >>> with open("path/to/csr.pem", "w") as f:
Alex Gaynor11b00cd2015-07-13 21:12:39 -040078 ... f.write(csr.public_bytes(serialization.Encoding.PEM))
79
80Now we can give our CSR to a CA, who will give a certificate to us in return.