Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Coding Like a Certificate Authority

00:00 In the previous lesson, you took the first steps to becoming a Certificate Authority by creating a private key and a public certificate with a public key inside of it.

00:08 In this lesson, you’ll switch roles—become Alice—and create a CSR and then switch roles back to Charlie, signing the CSR. Here’s a quick review. Charlie, the Certificate Authority, needs a public key, which you’ve created, a private key, which you’ve created, and the ability to sign CSRs. Alice, the site owner, needs a public key, a private key, and a Certificate Signing Request describing her site that she can submit to the CA. Now, you’re going to change roles.

00:41 You’re acting as Alice, and you’re going to create a Certificate Signing Request so that you can ask Charlie to sign it. In order to do this, Alice needs a private key and a list of hostnames to be associated with the certificate.

00:54 Alice is going to use the same PrivateKey module you created earlier to create a private key and then use that to build the CSR.

01:03 The CSR will also be built in a class using a factory pattern similar to the key patterns. This factory will require a list of hostnames that are valid for the key, information about the subject, and needs to be signed by Alice’s private key.

01:16 Like the public and private key, you’ll also need a mechanism for saving the CSR to a PEM file so it can be sent to the CA. Finally, all of this will be combined together into that single key generating script, which will go through all of the steps in the process.

01:32 You’re about to dive deep into another long coding example. Don’t forget, you can download the code in the Supporting Material dropdown attached to this lesson.

01:42 This is the definition of the CSR object. It’s similar to the PublicKey object. It has a .generate() factory method, which takes a private key, a list of hostnames, and a dictionary of subject information. Because it’s a certificate—just like the public key—you need to create subject information, reusing the make_x509_name() function.

02:04 The resulting certificate from the CA has to be signed against a list of hostnames it’s valid for, so the CSR has to contain that information for the CA to approve. Lines 15 through 19 loops through a list of hosts and uses the SubjectAlternativeName object from x509 to create a list of those names.

02:26 Similar to the PublicKey, a builder factory is used. This time, it’s a CSR builder. The subject for the certificate is included, as well as the alt names provided above, containing the hostnames. Finally, an empty CSR object is created.

02:43 The builder factory is used to sign the CSR using the private key passed in, and that is attached to the .key attribute of the newly created CSR object.

02:54 It is then returned to the caller. Because the output of the CSR is the same kind of certificate as a public key, instead of reimplementing the .save() method, I’ve just inherited from the PublicKey class and overloaded the .generate() method.

03:11 Once again, I’m back inside of the generate_keys file. In this section, you’re acting as Alice with the intent of creating a CSR. In order to do that, you first need a private key. Line 25 and 26 generates a PrivateKey. This is no different than the one for the CA, but this one is for Alice. The key is being saved in "server-private-key.pem", and there’s a different password assigned because Alice doesn’t know the CA’s password. Take careful note of this. In the next lesson when you go to use this key, you’re going to need to know this password. Lines 29 through 36 populates information for the CSR. First, the name dictionary.

03:52 This names Alice’s company and the host "alice.example.net" where she would like to host an HTTPS server. The alt_names list contains the list of servers that will be valid for this certificate. In this case, 'localhost' and 'alice.example.net'.

04:09 If you’re self-signing certificates for internal use, you may only need 'localhost' in this situation. This is something else I want you to take careful note of. In lesson seven, when you go to use this, these hostnames will become important. Finally, the meat of it: line 38 and 39 generates the actual Certificate Signing Request.

04:29 It requires Alice’s server_private_key, the list of hostnames in alt_names, and the location information in the name_dict. Following the same pattern as before, the object is generated, and then the .save() method is called—this time, saving it in a PEM file called "server-csr.pem".

04:52 This is the contents of that PEM file. Doesn’t look much different. Once again, it’s a large ASCII blob of certificate information. The header, here, is the CERTIFICATE REQUEST, indicating that this is a CSR.

05:07 For the last little bit, you’ve been acting like Alice, generating the Certificate Signing Request. It’s time to switch back into the role of Charlie, the CA, and sign Alice’s CSR.

05:18 In addition to the CSR PEM that Alice submits to Charlie, Charlie also needs her public key and private key. You’re going to need to add a .load() method to the CSR object class to load in the PEM file, and then create a SignedKey class.

05:35 This will follow the same pattern as before. Using a factory object, it’ll take a CSR, the CA’s public and private keys, and it will sign the CSR—generating a signed certificate.

05:48 The SignedKey object will also need a method for writing this certificate to a PEM file. Once all this is done, the final step will be use the SignedKey object inside of the key generating script to finish off the whole process.

06:05 This file defines the SignedKey object. Similar to the CSR object, it inherits from PublicKey. This is because, once again, it’s issuing a certificate and can use the inherited .save() method. Using the pattern you’re now familiar with, there is a class method called .generate(), which acts as the factory. This also uses the make_builder() helper utility.

06:29 The only difference here is—because this is for a CA—the subject and the issuer are different. The subject is the subject from the CSR, and the issuer is the subject information from the CA’s public key.

06:43 Once the builder factory has been instantiated, a series of extensions are applied to it. You can think of the extensions as limitations that are being applied to the certificate.

06:53 These limitations are being read in from the CSR and were provided as part of that signed certificate request. Line 19 and 20 is where the work is done.

07:04 The builder factory is used to sign the actual certificate. The signature on the certificate comes from the CA’s private key. The builder returns the result, and—like before—this is stored on the .key attribute of the object created and the factory method returns the object.

07:24 And here’s the relevant part of the generate_keys.py file. Line 42 is where the CSR is signed. Signing it requires the CSR from Alice, the CA’s public key, and the CA’s private key.

07:38 Once the .generate() method is called, the SignedKey object contains the signed certificate. The .save() method is then called on the object, saving it into a file "server-public-key.pem".

07:50 This file is needed by Alice when she starts her HTTPS server. It’s the signed certificate associated with her domain.

08:00 And all of that work was to produce this one certificate. This is the certificate for Alice’s server. She can now host HTTPS and anyone with a browser that has Charlie listed as a CA will consider her site secure.

08:16 That was a lot of code in a lot of different files, so here’s a bit of a recap. The generate_keys file is a single program that acts as both Alice and Charlie—creating the appropriate keys, a CSR, and signing that CSR so Alice can use it. First off, a private key was created, stored in the file ca-private-key.pem, which is Charlie the CA’s private key. Secondly, a public key was created, stored in ca-public-key.pem.

08:46 This is also Charlie the CA’s key. To create a CSR, Alice needs a private key, so server-private-key.pem was generated. That key was then used to create a CSR.

08:59 It was signed and submitted to Charlie. Charlie takes the CSR and creates a new certificate, which is a public certificate that has been signed by Charlie the CA. Alice can now use this to run TLS on her web server.

09:16 Of course, because this is all happening inside of one script, you’re acting as both Charlie and Alice in this situation.

09:24 You’ve done the hard part. You’ve got the certificates. Next up, I’ll show you how to install that in Flask.

Become a Member to join the conversation.