Generating self-signed public keypairs is a staple of many involved in DevOps, system admin, network administration and other roles. They are useful for testing encryption configuration and even providing some level of encryption security, mainly for internal organisational HTTPS connections. The most common case for self-signed certificates is for use with Web Servers, but many other applications such as Elasticsearch, which use RESTful APIs, will benefit too.
What is self-signing?
When a web server offers a public key to an incoming client, how can the client trust it? How does it know that the web server represents the organisation it says it does? The answer to that is a Chain of Trust.
The Chain of Trust starts with a few organisations, called Root Certificate Authorities, whose details are baked-in to most browsers and other clients interacting with web services. They include Sectigo (Comodo SSL), DigiCert, Symantec, Thawte and others. In turn, they have authorised a larger number of Intermediate Certificate Authorities (CAs) who may then authorise other CAs or certificates for individual web servers.
When you visit an encrypted website, your browser checks the supplied certificate and based on the knowledge it has of the chain of Certificate Authorities, it will accept or reject that certificate. This process works well, but there are some drawbacks for those who need a certificate for internal or development purposes:
- It costs money
- It must be renewed – certificates typically don’t last longer than one or two years and cost more money for each renewal
- It takes time
The usual process
Usually, the process for obtaining such a certificate follows these steps:
- Create a public/private keypair for your website
- Create a Certificate Signing Request (CSR) file
- Pay fees and send the CSR file to an Intermediate CA for approval
- Wait for the Intermediate CA to approve your request
- The Intermediate CA sends back a signed public key certificate
- Install the Private key and the Signed Public key in your webserver
The self-signing process
You can remove a lot of the hassle of getting a web server certificate by eliminating time and cost restrictions: you can create your own. This eliminates steps 3, 4 and 5. Here is a comparison of the processes:
Your own chain of trust
The self-signing process is more efficient but comes at a price: the only person that will trust this certificate is yourself. In fact, browsers will produce a warning each time a self-signed certificate is encountered, with most of them offering the option to allow it anyway, along with the associated risks. While production, internet facing systems will find this situation intolerable, it’s acceptable in some circumstances for test and development purposes
Step-by-step to Self-signing
To demonstrate, we will use openssl, available on Linux and other Linux-like systems. The process is a little more involved than the diagram above represents, so these instructions are more detailed.
1. Create an openssl.conf file containing certificate values. This file will have information that certificates need to be valid. This includes:
- A Distinguished Name (DN) of your web server’s identity. Such as the web server’s Country, State or Province, Location (e.g. a city), Organisation, Organisational Units (such as departments) and the host name itself.
- Alternative names that the certificate might use. For example, you may install this certificate on a web server called server1, but you wish the certificate to be valid for other names it is used under, including
Contents of the openssl.conf file may look like this example:
2. Create a Private key. Generate a private key for your webserver. The number of bits here determines key strength and should be more than 2048:
3. Generate the CSR file. Using
openssl, you can generate a CSR file. In this example, the CSR file will be call
Note that the private key (
openssl.conf files are referenced here.
4. Create an x509 Extensions File. And here’s the weird gotcha! You would assume that since you have given alternative names in your original
openssl.conf file, that this would ensure your certificate knows the names you would like your server to be known. But alas, this is a bug with
openssl. If you read the x509(1) Linux manual page, under the Bugs heading, it states:
Extensions in certificates are not transferred to certificate requests and vice versa.
This means that we must tell openssl at the signing stage to include the alternative names that we have already given! Despite being a little inconvenient, it is relatively straightforward. We create an x509 extensions file (in this case, we’ll call it ext-x509.conf) containing the alternative hostnames only. For example:
Note here, that the
[alt_names] section is a copy of what exists in the
openssl.conf file. Note too that the name of the configuration in the
ext-x509.conf file is
Note also that if a change in the alternative name list occurs, this will need to be updated in both the
openssl.conf file as well as the
ext-x509.conf file too.
5. Sign the CSR file with your own public key. Using
openssl’s x509 capability, you can sign your own request with your private key you generated earlier. Most of the time a one-year (365 day) validity is sufficient. The resulting public key will be placed in the file
Note here the references to
- the CSR file
- the private key file
- the x509 extensions file
- the heading within that file,
6. Deploy and enjoy! This process will leave you with two important files:
- Your private key in
- Your public key in
- Your private key in
This will be all your web server will need to start using self-signed HTTPS!
I hope that this post was informative and useful. Skillfield regularly posts informative and interesting content on its blog, and runs free educational webinars, all focussed around solving problems in cybersecurity! Follow us on LinkedIn for more details!