Certificate fundamentals

From SaruWiki
Jump to navigation Jump to search

Certificates, an introduction

Digital certificates are an extremely important means to identify identities (of users, as well as of servers) on the Internet, or indeed on most any network. For instance, we use them to encrypt network traffic when we use the HTTPS protocol. Thus, we really need certificates.

Now, as this article explains, you can either buy your certificates from a certificate authority like VeriSign, Thawte or Equifax Secure, but these certificates cost more than a couple of Euro's, and also need to be renewed (usually every year). So the other route, the one we'll be taking, is to create our own Certificate Authority (CA), and use that to sign certificates for our needs (secure webserver, secure mailserver etcetera).

Now, "creating a CA" sounds like grave installation and configuration work, but in fact a CA does not have to be an actual service, demon or program. A CA is more like a concept, at the heart of which lies the CA "root certificate". So if we obtain a little set of tools and generate our own root certificate, then we're in business.

Creating the Certificate Authority (CA) - preparations

To generate the root CA for our own little organization, we first need tools. These tools under Debian come with the OpenSSL software - which you'll usually find already installed (if not, run apt-get install openssl). Now to generate the CA root certificate, we'll use a shell script from the OpenSSL package: /usr/lib/ssl/misc/CA.sh, which together with the configuration file /etc/ssl/openssl.cnf can create our CA root certificate. To that end, we'll first need to decide on some parameters.

Deciding on CA parameters

How strong do we want our root certificate? 1024 bits is the default, but the stronger, the better. We suggest 4096 bits - not because 2048 isn't sufficient (even 1024 is still very very good, even in the year 2016), but because it's not necessary to keep a CA's key length very low, and 4096 can be expected to remain pretty secure until after 2030 (see here).

How long should our CA root certificate remain valid? The longer, the more convenient - but maybe some day in the future, you feel you don't want certificates issued ten years ago to just lie around, expired but otherwise valid. Expiry of the root certificate that goes along with that certificate might help you. So what's an appropriate time for your root CA? That depends. For our home CA, we use 15 years. For a business, the cost of providing new root certificates to all computers, employees, and maybe customers, can be so high that you'd rather have 25 years - or maybe security is paramount, and 5 years is long enough for you. We can't say - but our home CA's use 15 years, because we feel that that's a nice intermediate value. 15 years, including about 4 leap days, comes to 5479 days.

Where do we want to store our CA root certificate? By default, the CA.sh script feels it must store all generated certificates in ./demoCA. That's not very handy for us. We rather have a central location like /etc/ssl/ca on our home server. Yes, it's sound advice to keep the root certificate on an offline machine and all that, but this is for a self-signed certificate, and if this particular directory gets compromised, then so is the whole home server, and we've got greater issues than the loss of a self-signed private key.

How long should any generated certificate be valid? The default value that the CA.sh script provides is one year. We find that enough - although we add 7 days to accommodate some overlap when having to regenerate the certificate upon nearing the expiry date (note: we really want to replace certificates prior to expiry :-)

What "company" data will we enter in the certificate? Several fields must be entered, some of which you could fill out at will. However, it's not exactly clear why you would want to confuse people trying to authenticate you, your webserver or some other connection by filling out, for example, the country with an incorrect or even non-existent code. On the other hand, you can keep your own privacy in mind, and not fill in your full name, but rather your website's name, at the "common name" section of your CA root certificate. Again, this depends on what you're going to use your CA for. We at saruman.biz decided to use the following values:

  • Organization name: Saruman.biz. We're private persons, not companies, but we want to maintain a minimum of privacy, so we've put this fake entity name here.
  • Country: NL (that's the Netherlands)
  • Province: Utrecht. Yep, that's a province in the Netherlands, and I happen to live in it.

Maybe you want to provide more default information to your CA setup; just look further down on how to.

So the information we've decided upon is like this:

Parameter value
root certificate encryption 4096 bits
root certificate validity 5479 days (15 years)
certificate store /etc/ssl/ca
default certificate validity 370 days (1 year)
Organization name Saruman.biz
Certificate province/county name (default) Utrecht
Certificate country name (default) NL

Editing the openssl.cnf configuration file

When generating certificates, the OpenSSL tools check the configuration file /etc/ssl/openssl.cnf. It is necessary to match the parameters in there with the choices and changes of the previous sections, and also it's handy to change some of the default parameters that certificates require upon generation. It's important to remember that these parameters will be asked every time you generate a certificate, but it's ofcourse pretty handy if the default value is set for your situation, so you can just hit that big <enter> key.

First up, we'll change the dir variable in section [ CA_default ] to match the dir from the CA.sh script. Then we find default_days and change it to our default certificate lifetime: 370 days. Furthermore, we find the certificate strengt in the [ req ] section; we can change it to our preferred value of 2048 bits.

Now we can put in the optional bits: the default values. Not necessary, but handy. We go to section [ req_distinguished_name ] and fill them in. For this, we again use the table we've previously compounded.

So the changes we've made will amount to something like this:

[ CA_default ]
dir             = /etc/ssl/ca
...
default_days    = 370
...
[ req ]
default_bits    = 2048
...
[ req_distinguished_name ]
0.organizationName_default  = Saruman.biz
stateOrProvinceName_default = Utrecht
countryName_default         = NL

Especially the last section is, again, a pretty arbitrary choice. You could choose not to provide customized default answers (in which case you're stuck with Internet Widgets Pty from Some-State, AU as the default answers). There are more default values in that section of the openssl.cnf configuration file; go in there and decide what you want.

Editing the CA.sh script

Unfortunately, not everything we want to change is actually set from the openssl.conf file: we'll need to alter some parameters for the root certificate that are hard-coded in the setup scripts.

We find the scripts in /usr/lib/ssl/misc/. Note that there are two different scripts: CA.sh, a shell script, and CA.pl, a perl script. Since we're more into shell scripting than perl programming, we go for the shell script. So we edit /usr/lib/ssl/misc/CA.sh; find the two lines near the top that define the variables DAYS and CADAYS, and set these to what we want them to be. Then, a lot further down, we find the line that's responsible for creating the CA root certificate itself, it's the line that goes $REQ -new -keyout ${CATOP}/private/$CAKEY -out ${CATOP}/$CAREQ (well actually it's split out over two lines). Here, right after -new we add -newkey rsa:4096.

With all these changes, the three relevant sections in CA.sh will be changed to something like this:

DAYS="-days 370"        # 1 year
CADAYS="-days 5479"     # 15 years
...
echo "Making CA certificate ..."
$REQ -new -newkey rsa:4096 -keyout ${CATOP}/private/$CAKEY \
            -out ${CATOP}/$CAREQ

the Certificate Authority root certificate

Now with the basic information in place, we can go about generating the certificate itself, and putting it to use. Well, actually we're not going to generate one certificate, but two: the public one, that we give out to anyone that might want to check the validity of any certificate that claims to have been issued by the Saruman.biz CA, and the private one, with which we can digitally sign certificates so as to prove that they're really issued by said Saruman.biz CA. This is also referred to as a "key pair".

Creating the CA root certificate key pair

To generate the CA's public and private root certificate, as root, execute

/usr/lib/ssl/misc/CA.sh -newca

With the defaults set as given above, you still get some questions. One is "CA certificate filename". This actually requests from you another certificate with which to sign the one we're creating. However, we're generating our root certificate, so we leave this empty and just hit <enter>.

Next question is for the PEM passphrase. Make that a strong passphrase or password, keep it very secret, and don't forget it! (and DON'T write it on a piece of paper; use something like keepass to store your secret passwords).

For the next set of questions, you probably have filled in some of the defaults. If you want to leave some entry blank, fill in a period (.). You'll have to provide the country code, province or state, locality (like city; Saruman.biz leaves this empty), Organization Name, Organizational Unit name (again, empty), and finally the Common Name. This last question is pretty important: the name you put in here is the name under which your CA will go for the next 15 years!! So don't put in a "funny" name, a bland name, or whatever. We put in "Saruman.biz Root CA", somewhat like official root CA's like "Equifax Secure Global eBusiness CA-1" or "Macao Post eSignTrust Root Certification Authority". The script also asks for an email address, which you may or may not provide, a challenge password, and an "optional company name", both of which you can leave blank because we're not sending a certificate signing request out to someone else, but signing it ourselves.
Having provided this information, we've actually already created one half of the key pair, namely the private key. It'll be /etc/ssl/ca/private/ca.pem, and is protected by our chosen very strong password. However, we now need the public key, self-signed with the private key.

The next step in our CA creation process thus again asks for the passphrase. Since this is the second step in a two-step process, we again put in the passphrase we've already provided. However, now the shellscript uses this to unlock the private key we've (already) created, and then use it to sign the public key we're now creating. However, the passphrase is all that it asks. It now generates a signing request (/etc/ssl/ca/careq.pem), then uses the private key to sign it, and then generate the public key, to be found in /etc/ssl/ca/cacert.pem. You can remove careq.pem after you've inspected the cacert.pem.

So now we've got two root certificates, namely

  • private key /etc/ssl/ca/private/cakey.pem, and
  • public key /etc/ssl/ca/cacert.pem.

NEVER send your private key out to ANYONE! Protect that key, and its passphrase, with your life. If you lose the file, lose the passphrase, or the key gets compromised (lost to an unknown party) then you've got to replace your root certificates AND you'll have to re-issue ALL certificates that you've ever signed (we're not going into certificate revocation here).

You can inspect your certificates (when you're in directory /etc/ssl/ca) with commands like this:

openssl x509 -in cacert.pem -noout -text
openssl x509 -in cacert.pem -noout -dates
openssl x509 -in cacert.pem -noout -purpose

Note from the last command above, that this certificate is obviously a root certificate: it can verify the signature of everything but the kitchen sink.

In the same manner you can inspect your private key - note that you'll have to provide the passphrase to complete this command:

openssl rsa -in private/cakey.pem -noout -text

Note that this can be used to check if the private key and certificate belong together: the `modulus' and the `public exponent' portions in the private key and the certificate must match. But since the public exponent is usually 65537 and it's bothering comparing long modulus you can use the following approach:

openssl x509 -in cacert.pem -noout -modulus | openssl md5
openssl rsa -in private/cakey.pem -noout -modulus  | openssl md5

And then compare these really shorter numbers (and again, you'll have to provide the passphrase to read the private key). Both commands will output something like:

(stdin)= 96a281eca852b794a907186a9703ddf4

With overwhelming probability they will differ if the keys are different.

We've got the CA certificate, now what?

With the root CA certificates available to us, we've got the following things to do:

  • guard very carefully the public and (especially) the private key file;
  • sign certificates for our own use;
  • distribute the public CA certificate to every machine/person that may need to verify certificates that we've signed.

The first means we've got to keep a copy of the private key file in some other, safe location, and we've got to secure the private key on the server where it sits - both the machine and the file. At the very least, you have to make sure the private key is owned by root or an administrative account, and is not world-readable. It might even be wise to remove the private key altogether, and keep it on a USB stick, and only read it when signing certificates.

The second thing means we've got to generate keys for SSL and TLS connections, just as we need them. This is covered in our creating digital certificates section.

The last point means we need to send out our public CA certificate. In some cases, you can provide others with your .pem file, but in other cases you're better off providing a simpler .crt file. The difference is explained nicely at the ssl.com site To create a public CA certificate in .crt format you can issue the following command:

openssl x509 -outform der -in cacert.pem -out cacert.crt

By the way, it's usually better to distribute the public certificate with a more recognizable file name, such as saruman.bizRootCA.crt