Creating Public and Private Keys
00:00 In the previous lesson, I discussed asymmetric key exchange and introduced you to the concept of a m 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:21 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.
00:39 So, it isn’t just enough to become a Certificate Authority. 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:26 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.
Charlie verifies Alice’s identity and then signs her certificate. Alice can use this certificate to host HTTPS on her web server. When Bob connects to
https://alice.example.net, he receives the corresponding certificate.
01:57 His browser can then verify the authenticity of this certificate with the Trusted Third Party. 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:31 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:19 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:30 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
You may want to create an object by loading one from a file. So the method has to be done separately. The key generation happens on lines 10 and 11.
rsa.generate_private_key() with some settings returns a key that’s going to be used.
05:12 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
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
PrivateKey object and this
PrivateKey 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.
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
The final parameter to
make_builder() is a flag to indicate whether or not I’m building a CA certificate. There’s a small change in behavior necessary when building a CA certificate, and I want to be able to reuse
make_builder(), so I pass in this flag.
11:21 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.
The 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
public_key object, and then the class returns it.
Here’s part of the utilities file defining the
make_x509_name() function. This function’s fairly simple. All it does is take the country, state, locality, organization, and hostname that are associated with this certificate and build
x509.NameAttributes out of them.
date_range() method in the utilities 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.
Lines 38 through 40 specify that this certificate is going to be for a CA. This is actually an updated version of this lesson. The original version did not have lines 38 through 40, and it worked fine for a certain version of
If you happen to be using
curl with a build prior to 2019, it would work without these three lines. Conversations in the forums show that it stopped working all of a sudden. In digging into this, I discovered that the newer version of
curl uses TLS 1.3.
This call also has
is_ca set to
True to explicitly require that this is a public key for a CA. Once
.generate() is called, the
PublicKey object now has a key inside. All of this is stored in
Become a Member to join the conversation.