SSL Certificates

From Jonathan Gardner's Tech Wiki
Jump to: navigation, search

Introduction

You need to understand the issues surrounding encryption before you can understand SSL certificates. Please read that article first.

Here's a quick review. Answer these questions without hesitation and you are ready to continue.

  1. What is a public key? Who should be allowed to have a public key?
  2. What is a private key? Who should be allowed to have it?
  3. What is the only difference between a public key and a private key?
  4. What is a symmetric key pair? Why are they used in specific instances? Why are they not used in other instances?
  5. Why does the client need to know the public key of the host before attempting a connection?
  6. Describe the various weaknesses of different encryption techniques.
  7. Describe what a signature collision is.
  8. Describe how one might guess a private key.
  9. What does it mean to "securely sign" data? How do you sign it? How can others verify that the signature is correct? How can a signature be forged?
  10. What does it mean to "encrypt" data? How is it encrypted? How can the intended recipient decrypt it? How can data that is encrypted be read by someone who doesn't have the correct keys?

SSL is a general concept. There are many, many compatible implementations. However, the one system I describe is the OpenSSL system, which is open-source. It is freely available on all Linux systems, and is also available on Windows and Apple platforms as well.

How Does SSL Work?

SSL stands for the Secure Socket Layer. Its purpose is to establish a secure TCP/IP connection between host and client, without any chance of snooping or man-in-the-middle attacks. Although SSL is principally used for serving webpages over HTTP, it is also used for other protocols, such as IMAP, POP, and SMTP, and even the contents of email messages. SSL can be used almost anywhere encryption or secure signatures are needed.

How does it do this?

  1. Hosts generate a public/private key pair. They keep the private key secret, perhaps even password protected. The public key will be freely distributed to whomever wishes to see it. SSL addresses the problem of getting the right public key in the hands of the people who wish to converse with the actual owner of the private key.
  2. A trusted third-party, the Certificating Authority (CA) verifies that the owner of the host is the owner of the host, and certifies that the public key is valid by signing it with their own private key. This information, along with what information they certified, is put into the certificate file and given to the owner. This is the certificate.
  3. The host distributes the public key and the certificate that the CA generated. If the client trusts the CA, they should trust the public key signed by the CA, as long as all the credentials match. For instance, the domain name that the host responded to has to be the same domain name that the CA certified. Also, the certificate should not be expired.
  4. The client then creates a symmetric key pair and sends it, encrypted with the host's public key, to the host.
  5. The host and client then begin communicating using the symmetric key pair.

As you can see, the most complicated part is the generation of the certificate. What does the CA want to verify? That depends on the CA, but typically it is just the email address or the domain name.

There are three files you have to keep track of:

  1. The private key. This should be kept secret and shared with no one, not even the CA. It should be protected with a password, a password that only the two or three people who need to know it know it. A copy of the password may be kept in a very secure place, like a safe.
  2. The public key. This is public knowledge and should be freely distributed to those who ask for it, including the CA.
  3. The certificate. This is generated by the CA and is signed with the CAs own keys. It certifies that the public key really is the public key for the party it says it is for. This certificate file should be automatically served up at the beginning of every SSL session. Its signature is verified, and if the client accepts the CA, then they should accept the public key in the certificate.

How Do I Generate a Key and a Certificate?

You may want to get the CA.pl utility. It'll make your life a lot, lot easier. This is available in the openssl-perl RPM for Fedora.

However, you may just want to learn the openssl commands yourself!

(Thanks to http://www.yatblog.com/2007/02/27/how-to-create-a-ssl-certificate/)

Before we begin, let's set up some environment variables. I like to keep track of when the keys were generated and certified, so I set it up thusly:

CURDATE=`date +%Y%m%d`
CURHOST=server 
KEYFILE=$CURHOST-$CURDATE.key
CSRFILE=$CURHOST-$CURDATE.csr
CRTFILE=$CURHOST-$CURDATE.crt

Generate a Key

The first step is to generate a public/private key pair. This is done in OpenSSL as follows:

openssl genrsa -out $KEYFILE 1024

This generates a key without a password. If you want the extra security of having a password, then use this command:

openssl genrsa -des3 -out $KEYFILE 1024

After you generate the key, make sure it is only readable by the owner.

chmod 600 $KEYFILE

Generate a Certificate Signing Request (CSR)

Next, you need to generate a Certificate Signing Request (CSR). This will be sent to the Certificating Authority to sign your key.

openssl req -new -key $KEYFILE -out $CSRFILE

Would you like your defaults to be more sensible? Try editing /etc/pki/tls/openssl.cnf with your preferred defaults.

Note carefully: the Common Name for HTTPS certificates will have to match your domain exactly. That means, if you're serving up pages over HTTPS in response to requests to www.jonathangardner.net, then the Common Name must be www.jonathangardner.net. This is troublesome when you have multiple domains pointing to the same IP address. (See below on how to handle that. The short answer is you need multiple certificates.)

Get the CSR Signed

If you wish to pay a real CA to sign your key, server.csr would be the file to pass along. They will give you a file, the certificate, which you must never lose, at least until it expires. A cheap (free) CA is OpenCA, although they haven't penetrated very many applications yet.

If you are a cheapskate, or just playing around, you can sign your own key.

openssl x509 -req -days 365 -in $CSRFILE -signkey $KEYFILE -out $CRTFILE

Or, if you are running your own CA, you can sign the key following the instructions below.

Install the Key and Certificate File

This is pretty easy to do.

cp $KEYFILE /etc/pki/tls/private/$CURHOST.key
cp $CRTFILE /etc/pli/tls/certs/$CURHOST.key

How Do I Use a Certificate?

Using your key and your certificate is simply a matter of moving the files into the right place.

HTTPS with Apache

The Apache config file is a little bit obtuse. (On a Fedora system, this is found in /etc/http/conf.d/ssl.conf.) However, you'll want to look for a section like the following (grep is your friend).

SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key

Either rename those files, or leave them and overwrite them.

HTTPS with Apache Serving Multiple Domains

The multiple domains may include localhost.

Couple of notes:

  • If your host is available through multiple domain names, you're going to have to choose one and stick with it. That's because the client is going to access the HTTPS port through one domain and get a certificate for the other. It is going to complain loudly.
  • If you really want one host to support multiple domain names, you're going to have to mess with virtual IPs. This isn't hard, but it isn't easy. Give each of your domains a unique IP address. Have your server's network configured to answer for all of those IP addresses through a single ethernet connection. Finally, configure Apache to answer each IP as a different domain with a different certificate.

You'll notice a section call <VirtualHost _default_:443>. All you have to do is copy this to <VirtualHost IP address:443> and specify the crt and key file that should be used for that IP address.

Note that you can't branch on domain names. That's because Apache needs to know which section you're hitting before it has even read the first HTTP header, and the domain name is specific by the HTTP header. Let me explain more carefully.

  1. The user types (or clicks on a link to) https://www.jonathangardner.net/
  2. The browser application (Firefox or IE, etc...) looks up www.jonathangardner.net via DNS. It gets back an IP address.
  3. The browser application notices the "https" part, and so opens up an SSL connection to the IP address.
  4. The web server and browser application negotiate a connection via SSL. It is at this time that the certificate is checked. The web server has no way of knowing which domain name was used to connect to the server.
  5. If the browser application decides not to connect due to an invalid certificate, the connection isn't even continued.
  6. If the browser application decides to continue, then it will accept the public key and begin sending the HTTP request, including the "Host: www.jonathangardner.net" line. Only now can the web server tell which domain name the connection was made through.

If you need to experiment with this, a great way is to setup your network to answer for 127.0.0.1, 127.0.0.2, etc... and then configure your /etc/hosts file to have different names for the IP addresses, perhaps multiple names for one. Now you can start trying to connect to your web server via https through those domain names and IP addresses. See if you can get the right key/cert combination answered for each request through each possible domain name.

IMAPS / POPS with Dovecot

Dovecot handles the SSL config with these lines:

ssl_cert_file = /etc/pki/dovecot/certs/dovecot.pem
ssl_key_file = /etc/pki/dovecot/private/dovecot.pem

On Fedora, this file was found in /etc/dovecot.conf.

Note that the pem file is just a different name for the same thing. If you wanted to use the same key for Apache and dovecot, you can just have the following config:

ssl_cert_file = /etc/pki/tls/certs/localhost.crt
ssl_key_file = /etc/pki/tls/private/localhost.key

SMTPS with Sendmail

Sendmail configures SSL files with the following lines in /etc/sendmail.mc. Don't forget to rebuild /etc/mail/sendmail.cf after changing it.

define(`confSERVER_CERT', `/etc/pki/tls/certs/sendmail.pem')dnl
define(`confSERVER_KEY', `/etc/pki/tls/certs/sendmail.pem')dnl

Signing Emails with S/Mime

Forget it. No one uses it. See Email Security for a discussion why.

How Do I Get Self-Signed Certificates Accepted?

If you are using any reasonable system with SSL support, you will see an error message when you try to access your SSL site with a self-signed key. Not to worry! It's not the end of the world.

All you have to do is have the client import the certificate and accept it. This can be as simple as choosing "Always accept this certificate" or as complicated as having the user import the certificate from a file and mark it as good.

How Do I Operate a Certificating Authority (CA)?

NOTE: I don't have this working with apache just yet... I suggest using self-signed certificates.

As a CA, you need to do the following:

  1. Ensure that your certificate gets installed on the client software.
  2. Verify the people requesting you to sign their certificates.
  3. Sign the certificates.

This is not too difficult.

Generate a Keypair

To start, generate a keypair:

openssl genrsa -des3 -out CA.key

Generate a Certificate

Next, create the CA certificate:

openssl req -new -key CA.key -x509 -days 1095 -out CA.crt

Sign the CSR

Now, when you are asked to sign a CSR, do your homework, then sign the CSR as follows:

openssl x509 -req -days 365 -in $CSRFILE \
    -CA CA.crt -CAkey CA.key -CAcreateserial -out $CRTFILE

This will generate a certificate good for 365 days.

NOTE: This certificate seems to be invalid... I don't know what I did wrong.

How Do I Get My CA Accepted?

By default, your CA is unrecognized and untrusted. Your clients will need to import your CA.crt file into their application and trust it.

Firefox

On the Menu bar, click on "Edit", then "Preferences". The "Firefox Preferences" dialog will appear.

Click on the "Advanced" item and then the "Encryption" tab. Then click on the "View Certificates" button. The "Certificate Manager" dialog will appear.

Click on the "Authorities" tab and then on the "Import" button. (TODO: Complete the last few steps.)

That's the hard way. Here's the easy way.

Install the certificate file for your CA somewhere on a web server. Users who browse to that page will be asked if they want to recognize that CA. If they accept it, and check off the web box for web pages, then it will be installed.

Sendmail

Sendmail checks the certificates before it sends mail. According to the line in the configuration below, it will look in /etc/pki/tls/certs, and any certificate there will be accepted as a CA.

define(`confCACERT_PATH', `/etc/pki/tls/certs')dnl

How Do I telnet Over SSL Connections?

openssl s_client host:port

What do I do when my certificate expires?

Hopefully, long before your certificate expires, you generate a new key and obtain a new certificate following the directions above. Then you simply install the new private key and certificate on all of the machines that were using the old key and certificate.

It is suggested that the older keys are, the more likely they are to be compromised due to a variety of factors, including such human elements as employee turnover or laziness in keeping the password secret. So it's a good thing you are required to do this from time to time.