Overall information security is one of the most important topics in the industry right now. With large scale hacks like Equifax and others, it's becoming increasingly difficult to protect information. System administrators follow general best practice in protecting external systems, and establishing trust with large scale certificate authorities. Very often though, I see administrators position blind trust inside their environment; They accept self-signed keys without a second thought. This can create issues of trust inside of an environment. There is a better way. By forging our own certificate authority, we can create a simple mechanism for trust.

TLS/PKI Primer

So what is TLS, and how does it work? Well, the answer can be very complex, and is a great read on its own, but I will give you a simple primer here.

TLS (Transport Layer Security) is a very simple way for us to establish a chain of trust + also a path for encryption of data in transit. The most common use of TLS is with displaying a secure web page. TLS establishes trust through a PKI (public key infrastructure).

PKI is a way for systems and services to identify themselves without compromising their secret. They can provide a public key which a client can create an encrypted challenge with. Then, using the corresponding private key, the server can send back the message, verifying that they have that private key.

A CA (Certificate Authority), is when a central certificate and key has signed a subordinate certificate for another host. This allows us to trust the CA without having to trust individual certificates. We can follow the chain back to the root that we trust.

On the public internet there are several CAs that are distributed to all systems, but that trust store can change, and you can add your own personal CA. With a personal (or company-wide) CA you can sign certificates for your internal resources, and distribute that CA's public key to your infrastructure to trust.

Today we're going to create an example CA, show you what to install, and sign a certificate. We're also going to do some certificate inspection so you can quickly see what we're creating.

Following these steps you should be able to quickly get off the ground with your own, internally trusted, CA.

The Dawn of the CA

Creating a certificate authority is blindingly simple on Linux or OS X. For windows you will need to install OpenSSL. More details on that process can be found here: https://wiki.openssl.org/index.php/Binaries

NOTE: This is a simple way of creating a CA, for production use, please follow my next guide.

Creating your CA only takes the following two commands:

openssl genrsa -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.pem

These two commands are doing 2 things:

  1. Generating a private key for our CA with a key length of 4096.
  2. Creating our CA certificate and signing it for 3650 days using a sha256 signature algorithm.

During the second step, we're going to be asked a few questions about our certificate. Answer these to the best of your ability.

You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:Texas
Locality Name (eg, city) [Default City]:Plano
Organization Name (eg, company) [Default Company Ltd]:David Leonard
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:David Leonard Root CA
Email Address []:david@davidops.com

You will now be given a couple files in your working directory:

  • rootCA.key - Your CA Private Key
  • rootCA.pem - Your CA Certificate

You can take rootCA.pem and distribute it to your clients as a CA to trust. Keep your private key secure and private. If your private key is compromised, anybody can sign certificates as your CA.

We can inspect our rootCA.pem as follows:

╰─$ openssl x509 -in rootCA.pem -text -noout 
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            89:50:07:82:f8:fc:d4:e1
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, ST=Texas, L=Plano, O=David Leonard, CN=David Leonard Root CA/emailAddress=david@davidops.com
        Validity
            Not Before: Oct  2 18:48:22 2017 GMT
            Not After : Sep 30 18:48:22 2027 GMT
        Subject: C=US, ST=Texas, L=Plano, O=David Leonard, CN=David Leonard Root CA/emailAddress=david@davidops.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:

snip - We're going to end the output here because we have already gotten our important information. We can see the issuer is the Root CA, and the subject is the Root CA. Yes, every root CA is self signed. We can also see or validity for ~10 years (give or take leap years). We can also see the serial number of our CA, this is a great tool to identify that you have the correct CA, because as you saw, anyone can generate this CA with this subject, but the serial is unique to OUR CA.

Creating the CSR

Now that we have our CA that can sign things, we need something to sign! What we need to make is a CSR, or Certificate Signing Request. This is created using a private key on our host that we want a certificate for. We provide the CSR to the CA, and the CA provides back our signed certificate. We can then setup whatever our secure host is (website, chat system, email, etc) to use that certificate and the corresponding private key.

To make a CAR, we need to make a private key, and then we can make the CSR. Luckily we can do this all in one command:

openssl req -new -newkey rsa:2048 -nodes -keyout host.key -out host.csr

This will ask you a the same set of questions as before, but this time there is one that is particularly important. You need to set your Common Name to the url of the endpoint you wish to protect.

NOTE: At this point, some people familiar with certificates will point out that were not creating whats known as a SAN (Subject Alternative Name). In production use cases you will want to define a SAN (or a few!), but this guide is designed to encompass the core concepts. If you want to see how to create CSRs for production, please visit my follow up post.

╰─$ openssl req -new -newkey rsa:2048 -nodes -keyout host.key -out host.csr
Generating a 2048 bit RSA private key
.................+++
.........................+++
writing new private key to 'host.key'
-----
You are about to be asked to enter information that will be incorporated into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:Texas
Locality Name (eg, city) [Default City]:Plano
Organization Name (eg, company) [Default Company Ltd]:David Leonard
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:mysite.homelogin.net
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

This will create the following files:

  • host.key
  • host.csr

We can now transport that csr to our signing CA, and we can have our CA sign this certificate. In good practice, we should probably inspect our CSR:

╰─$ openssl req -text -noout -verify -in host.csr
verify OK
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=US, ST=Texas, L=Plano, O=David Leonard, CN=mysite.homelogin.net
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:

snip - Once we have verified that everything looks correct, we can sign the certificate:

╰─$ openssl x509 -req -days 360 -in host.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out host.crt -sha256
Signature ok
subject=/C=US/ST=Texas/L=Plano/O=David Leonard/CN=mysite.homelogin.net
Getting CA Private Key

This command has provided us with the corresponding host.crt. We can now take this certificate file back to our host, and install it with the private key into our software.

Conclusion

There we go! We have successfully created our root CA with a corresponding host certificate. Overall this does get the job done, and if you decide to trust your root CA, you would be good to go. Though with that, we took some major cuts to get to the simplest form. Overall this should not be used for production, and I am working on a follow up guide for a more production ready output. To list some (but not all) of the shortcuts:

  • We did not create a passphrase for our rootCA, this means anyone with the actual key can sign certificates. This creates a somewhat 2nd factor with the root CA. Always signed any private key in use.
  • We did not create any intermediate CAs, this doesn't allow us to distribute trust. This means that everyone has to use the root CA to create certificates. If we created intermediate CAs, we could limit the use of those intermediates to individual groups.
  • We did not take advantage of CRLs, revocations are impossible without this, severely limiting our ability to take away trust.
  • We don't use any openSSL config files, these config files eliminate human error when creating/signing certificates.
  • We don't setup any OSCP, also limiting our ability to revoke certificates.

Hopefully you found this article useful. If so let me know on social media. Stay tuned for my follow up post and I will see you next time!