SSL Certificates
Contents
- 1 Introduction
- 2 How Does SSL Work?
- 3 How Do I Generate a Key and a Certificate?
- 4 How Do I Use a Certificate?
- 5 How Do I Get Self-Signed Certificates Accepted?
- 6 How Do I Operate a Certificating Authority (CA)?
- 7 How Do I Get My CA Accepted?
- 8 How Do I telnet Over SSL Connections?
- 9 What do I do when my certificate expires?
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.
- What is a public key? Who should be allowed to have a public key?
- What is a private key? Who should be allowed to have it?
- What is the only difference between a public key and a private key?
- What is a symmetric key pair? Why are they used in specific instances? Why are they not used in other instances?
- Why does the client need to know the public key of the host before attempting a connection?
- Describe the various weaknesses of different encryption techniques.
- Describe what a signature collision is.
- Describe how one might guess a private key.
- 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?
- 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?
- 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.
- 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.
- 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.
- The client then creates a symmetric key pair and sends it, encrypted with the host's public key, to the host.
- 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:
- 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.
- The public key. This is public knowledge and should be freely distributed to those who ask for it, including the CA.
- 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.
- The user types (or clicks on a link to) https://www.jonathangardner.net/
- The browser application (Firefox or IE, etc...) looks up www.jonathangardner.net via DNS. It gets back an IP address.
- The browser application notices the "https" part, and so opens up an SSL connection to the IP address.
- 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.
- If the browser application decides not to connect due to an invalid certificate, the connection isn't even continued.
- 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:
- Ensure that your certificate gets installed on the client software.
- Verify the people requesting you to sign their certificates.
- 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.