aboutsummaryrefslogtreecommitdiffstats
path: root/docs/x509/tutorial.rst
blob: 565b6d3fcfbc9046f1b0dca448a69666c2244a7c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
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.