Self-signed HTTPS SSL Certificate for localhost (127.0.0.1) Domains
This post talks about how to create a self-signed SSL certificate for localhost and provides a short info section about encryption, digital certificates and certification authorities (CA). Certification of localhost is especially useful to set up a web development test environment capable of handling HTTPS requests. Everything was done using Ubuntu 22.04.2 LTS.Structure
- Part A: Short introduction to public/private key encryption and digital certification.
- Part B: Creation of SSL certificate for localhost.
A. Introduction
Briefly, some important principles to understand the proceeding of certifying localhost.Asymmetric Encryption using a public/private Key Pair
In an asymmetric encryption process, each subject creates a public and private key pair.- The public key is handled over to another subject and is used to cipher data, e.g. to encrypt an email message text. This email text will then be sent back to the owner of the private key.
- The private key stays at his owning subject and is kept secretly. The key is used to decipher data which has been encrypted using the belonging public key.
- Metadata does not get encrypted, e.g. the origin of an email message.
- There is no encrypted information about the sending subject. That is, the owning subject of the public key does not verify its identity.
- Asymmetric encryption is often slow.
- Asymmetric encryption only works in both directions (subject 1 sends to subject 2 and the other way round) if both parties have a public/private key pair and the public keys are distributed under each other.
Symmetric Encryption using only one single Key
In a symmetric encryption process, there is only one key for encryption and decryption. The problem is, that one has to guarantee that this key is sent to the receiver securely. However, symmetric encryption is much faster. Therefore, one often exchanges at the beginning of a communication process a symmetric key asymmetrically (i.e. the symmetric key exchange uses an asymmetric private/public key encryption method) and then uses symmetric encryption for the rest of the conversation.Digital Signatures - An Asymmetric Signing Process
The digital signature process is also based on a public/private key pair and used for sender authentication. Again, the public key gets distributed to receivers. However, now, the private key is used to create an encrypted signature. The receiving subject uses the public key to decipher the signature and to see if it is really from the expected sender. Digital Signatures provide evidence of an electronic message's origin, identity and status. They do not encrypt the message's content. Encryption of contents bases on both, asymmetric and symmetric ciphering processes.CA - Certification Authorities
CAs are trusted third party institutions and part of the PKI (Public Key Infrastructure). Their main purpose is to create/store, sign and issue digital certificates. Most common CAs are- Digi Cert
- Let's Encrypt ...
What are Digital Certificates (aka Public Key Certificates)?
Digital Certificates are for sharing public keys. A digital certificate cryptographically links together a public key and its owner (its origin). It guarantees that a public key belongs to the subject which claims to be the origin of the public key. A digital certificate also ensures that its owner is trustworthy in terms of encrypting communictation processes. Note, I am not saying that the subject won't do any bad things. If it does bad things, then, at least with encrypted data traffic. In other words, communication over a public key with a trustful digital certificate is based on a valid asymmetric encryption. Valid means that- good encryption algorithms are used
- electronic messages do have a digital signature, i.e. the sender is trustful
- electronic message content is encrypted
What are Root Certificates?
Root certificates are the center of trust. Each CA has its own root certificate with the first private/public key pair to create a digital signature for other (intermediate) certificates the authority will issue. That is, each certificate out there on the web can be traced back to one of the CAs root certificates. For more information, see "chain of trust" or "certificate chain". The important thing to remember is that each valid certificate has to be a child of a root certificate from one accepted big CA like Digi Cert etc ...B. Certification Process for localhost Domain (IP 127.0.0.1)
During a web development, it is useful to have a trusted certificate for your localhost domain. For example, to test https:// and so on. However, it is not feasible to go to Digi Cert or any other trusted CA since they will not issue a certificate for localhost (or IP 127.0.0.1). Domain name 'localhost' is simply not known to them and they do not issue certificates to domain names which are not registered. Note, that this also means, that even if we just create a certificate by ourselves (e.g. via OpenSSL), it is not possible to trace back this certificate to a trusted root certificate, and there is no browser which will accept our certificate if there is no connection to a root certificate.Solution: Establishing our own CA with a valid Root certificate
We simply create our own CA with a trusted root certificate, and this CA issues a certificate for localhost.- Step: Creation of CA Root certificate (or in other words, creation of our own CA) Our own CA mainly consists of three files: Our own CA mainly consists of three files:
- RootCA.pem: A container file. This container owns the root certificate and public key. Those *.pem files will be presented to a client, e.g. your browser, and then the client knows and trusts the CA. More on this topic is under point 3.
- RootCA.key: The private key file, keep it secret and safe (although it is just for localhost but keep private key files safe, at least to get the awareness to do so as best practice).
- RootCA.crt: The public root certificate file itself.
- Step: Creation of the extension, certificate and key file for localhost:
- domains.ext: File contains information about the domains (in our case that is localhost domain) for which we want to have a certificate. Later, we will handle this file to our RootCA to deliver the necessary data for the certification process.
- localhost.crt: The public key file for localhost.
- localhost.csr: The certificate signing request file. A file containing information about the website, service, domain etc. OpenSSL creates that file and handles it to the CA during the certification process.
- localhost.key: The private key file for localhost.
- Step: Let the Browser trust our own RootCA: All browsers are shipped with .pem files from all big CAs (Digi Cert etc ...). So when our browser sees a certificate which roots back to one of its known root .pem files, it accepts the certificate. Therefore, we have to handle the .pem file from our RootCA to the browser to avoid nasty security warnings. If you use Firefox you can do this by clicking on
- Now you can use the localhost.crt and localhost.key files to configure your server ssl settings (e.g. nginx). However, this is not part of this article ... since it is another topic for another day or ohter tutorial out there.
$ mkdir CA
$ cd CA
The tool OpenSSL helps us to create the RootCA.key and RootCA.pem:
$ cd CA
$ openssl req -x509 -nodes -new -sha256 -days 150 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=DE/CN=My-Root-CA"
The option -x509 basically tells OpenSSL to create a "mini CA". The -days option defines the expiring date of our root CA. 150 days is just an example, you can choose any number. In the -subj option,
choose your two-letter country identification code, due to ISO31661-1. For example, "/C=US/CN=My-Root-CA" for United States and "/C=DE/CN=My-Root-CA" for Germany. For the other options, please refer to documentation
ISO31661-1.
OpenSSL also delivers the RootCA.crt file with
$ openssl x509 -outform pem -in RootCA.pem -out RootCA.crt
$ cd .. && mkdir CRT_localhost && cd CRT_localhost
Create domains.ext containing:
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1=127.0.0.1
You can use the following command for that or type it yourself using your favorite editor:
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
IP.1=127.0.0.1
$ printf 'authorityKeyIdentifier=keyid,issuer\nbasicConstraints=CA:FALSE\nkeyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment\nsubjectAltName = @alt_names\n[alt_names]\nDNS.1 = localhost\nIP.1=127.0.0.1' >> ./domains.ext
domains.ext has mainly two functions: First, say what certificates issued from our CA do (see keyUsage) and second, tell the domain name or names (alt_names section) we want to certify.
Finally, create localhost.crt, localhost.csr and localhost.key. We use OpenSSL again and our newly created RootCA files:
$ openssl req -new -nodes -newkey rsa:2048 -keyout localhost.key -out localhost.csr -subj "/C=DE/ST=YourState/L=YourCity/O=localhost-Certificates/CN=localhost.local"
$ openssl x509 -req -sha256 -days 150 -in localhost.csr -CA ../CA/RootCA.pem -CAkey ../CA/RootCA.key -CAcreateserial -extfile domains.ext -out localhost.crt
$ openssl x509 -req -sha256 -days 150 -in localhost.csr -CA ../CA/RootCA.pem -CAkey ../CA/RootCA.key -CAcreateserial -extfile domains.ext -out localhost.crt
Settings >> Privacy & Security >> View Certificates (under Security) >> Import
Navigate to your CA directory and select your RootCA.pem file. After the import, you can double-click and view your own RootCA file;)