Creating Public and Private Keys
00:00 In the previous lesson, I discussed asymmetric key exchange and introduced you to the concept of a Certificate Authority as a Trusted Third Party. In this lesson, I’m going to drill down further and start the discussion about how to become a Certificate Authority. First off, you’re probably never going to become a Certificate Authority that’s trusted by the browsers.
00:20 This is an arduous process with a lot of bureaucracy, which is good for us. We want it that way. It should be a difficult journey. Certificate Authorities are meant to be Trusted Third Parties. Of course, this does beg the question, “Trusted by whom?” The answer to that really is Windows, Mozilla, and Java. So, it isn’t just enough to become a Certificate Authority.
00:41 You have to be a Certificate Authority that’s trusted by these three organizations so that you are listed as one of their CAs. If you’re not listed as one of their CAs, then the end user—using a browser that uses these certificates—will not trust you. As an example, Mozilla’s CA policy is publicly available.
01:01 You can take a look at what is involved in going through it. So, why am I talking about being a CA for yourself? Writing the code will help you better understand how HTTPS and certificates work. And secondly, you can use this process to self-sign certificates.
01:25 Let’s go back to talking about Alice and Bob. Alice wants to host a web server. The first thing she does is create a Certificate Signing Request, which she sends to a Trusted Third Party. This is Charlie, the Certificate Authority.
02:03 This is how Bob knows that Alice is who she says she is—or at least, who her web server is. To do all of this, the Trusted Third Party needs a public key, a private key, needs to be able to receive a CSR, and sign a CSR.
02:30 The only thing that Bob needs is a browser that’s aware of Charlie’s Certificate Authority. If you’re using Firefox or Chrome, then these have built-in CAs for them. Inside of the settings, you can add a CA. So, for example, if you want to create your own Certificate Authority you could add it, but that’s only going to work for you and your instance of your browser.
Okay. So, let’s start becoming a Certificate Authority. In this case, you are Charlie. The first thing you need is a private key. The
rsa module has key generation mechanisms inside of it. Because the process involves a whole bunch of key management, I’m going to show you how to build a
PrivateKey class that can generate the key as well as read and write PEM files, the serialization of this key.
03:17 In addition to that, I’m going to build a separate script that actually calls this class and then generates the private key. What I’m about to show you is the first part of a fairly long example.
03:28 There’s over 200 lines of code explained in this lesson and the next one. You may find it easier to follow along if you actually have the code in hand. Don’t forget that the Supporting Materials dropdown contains a link to a ZIP file with all of the code.
The first method defined here is a class method called
.generate(). This is being used as a factory. In case you haven’t seen this pattern before, the idea here is instead of creating a
PrivateKey object in the normal way, you would call
This is stored locally in the
.key attribute of the
PrivateKey object that is being generated. Line 13 returns the object with the newly generated key inside of it. Because you’re going to want to load and save these keys from files, the
PrivateKey object has a
.save() method. Inside of this, it takes a
password and a
filename to store the key.
05:08 The library supports different mechanisms for serializing encrypted data. Line 29 is a factory for one of these serialization methods. It takes the prepared password as a parameter so that when the file is serialized, it’s serialized against this encrypted password.
This is the
generate_keys file. This is the file that actually gets executed and generates all of the keys. By the time the example is done at the end of the next lesson, I will have generated five different keys. As such, I’ve hidden big parts of this file and at the moment, I’m just showing the first key. Line 9 creates the
PrivateKey object, from the
PrivateKey module that was just demonstrated.
.save() method is then called, creating a file called
"ca-private-key.pem" Private keys are always password encoded, so the
.save() method takes a password, which is encrypted into the file. To use this key later, you’ll need to know this password. Here’s the resulting PEM file.
cryptography library also has a certificate management module called
x509, for the use of public keys. Additionally, I’m going to have to add a method to the
PrivateKey object so that it can load the PEM files that it saved before. The private key will be used to generate the public key. Similar to the
PrivateKey class, I’m going to create a
07:38 There’ll be a factory inside of that for generating the public key and—just like the private key—a method for writing the public key to a PEM file. Finally, I’ll add this to the key generating script, so when you run it it’ll generate the private key and then the public key.
To create a public key, you’re going to need your private key to be able to sign it. Earlier, I wrote the private key to a PEM file. Now, I need to add a
.load() method to the
PrivateKey object so that I can reload that PEM file and reuse it. Like the
.generate() method, this is also a class method, it’s a factory.
You will need to use that password in order to load the key. Line 18 prepares the password to be used to load the file. The cornerstone of this method is line 22. Using
load_pem_private_key(), it takes the encoded password and the data found in the file and returns it. That’s put on that
.key attribute of the
private_key object and this
private_key object is returned.
This method is an echo of the
.generate() method. Both of them create an empty object, get an RSA key, either through generating it or loading it from a file, and then return that object with that
Now, on to the
PublicKey. I’m using the same pattern here.
PublicKey has a
.generate() method that is responsible for creating an object with a
.key attribute. This time, the
.key attribute will be the public key. Up until now, I’ve been a little sloppy about my terminology.
You’ll see how these pieces fit together in a second. The certificate has information about the certificate holder in it. This is called the subject. The
make_x509_name() function is defined in a
utils (utilities) file, and it takes a list of name attributes—like your name and where you live—and creates this
10:54 This is what I meant before by being sloppy about my terminology. What the builder is ready to build is a signed public certificate. This is distinct from the mathematical key that RSA uses, which is the public key inside of the certificate.
builder gets signed with the private key and the end result is the X.509 certificate considered the public key. Like the
PrivateKey object, I’ve assigned this to the
PublicKey object, and then the class returns it.
date_range() method in the
utils file returns two dates—the starting valid date, which is right now, and the ending valid date, which is some number of days from now. Line 26 of
make_builder() uses this helper function to create a certificate that’s valid for 30 days.
builder is a factory for an
builder sets up the different properties of the certificate. You need a subject, you need an issuer, you need a serial number—which is randomly generated—you need the starting valid date, and you need the ending valid date.
It takes the
ca_private_key object instantiated earlier in the file, and this name_dict (name dictionary) with the locality information. Once
.generate() is called, the
PublicKey object now has a key inside.
Become a Member to join the conversation.