This is a detailed explanation of creating some SSL certificates with OpenSSL, getting them signed by CAcert.org, and then deploying them in a real system.
This HOWTO assumes some background knowledge in the fields of SSL and PKI (public key infrastructure) cryptography, but it's not really essential.
SSL (secure sockets layer) allows you to encrypt communications. It also allows you to perform authentication. When submitting data over an SSL-established connection, you can be reasonably sure that it won't be intercepted along the way.
However, SSL is often viewed as synonymous with trusted — and this is
simply not the case. When visiting a website with an https://
URL, this simply means that the owner of the website payed Verisign or someone
a large chunk of money. That's it. Unfortunately, the general public aren't
aware of this fact, and web browsers don't make them aware of it. Even for
advanced users who are aware of this, there are no real tools to assign levels
of trust. Instead, there is a binary authenticated or not
authenticated.
SSL works by way of certificates. A CA (certificate authority) has a private key which they can then use to sign other certificates. If a self-signed certificate from the CA is made available to somebody who wishes to check any given certificate, that client can use the self-signed certificate to validate the signature on any other certificate signed by the CA.
This is hierarchical; so as long as the root certificate is made available, an arbitrary chain of certificates rooted with the CA can be verified.
CAcert.org is one such root CA. Unfortunately, their root certificate is not included by default in most applications, but it's usually pretty simple to add. Once added, any certificates they have signed will automatically be verified.
The first thing you'll need to do is head over to CAcert and hit the Join link. This is a typical signup process where they email you a link which then activates your account.
If you're really security-conscious, you can do what I did and base-64
encode a bit of data from /dev/random
and use that as your
passphrase. Of course, this isn't memorable, so you should store it in some
form of AES-encrypted file (I use kwallet).
Assuming that you've bought a domain, say mydomain.dom
, you now
want to generate a server certificate for it, and for subdomains like
www.mydomain.dom
.
The first step is to prove that you own the domain. Choose Domains -> Add and enter the domain name. CAcert.org seem to do some DNS checks and offer the email addresses of the registered admins; but you can also choose root@, hostmaster@, postmaster@, webmaster@ or admin@ domain. Once you've chosen the address, you'll receive an email with an activation link; following this will then prove that you own the domain.
Now you'll need to generate a private key and a certificate signing request. This requires the openssl commandline client. First, generate the private key with:
# unencrypted, 4096-bit key openssl genrsa -out privkey.pem 4096 # alternatively, encrypted openssl genrsa -des3 -out privkey.pem 4096
The key length recommended by the OpenSSL key HOWTO is at least 2048 bits; I'm using 4096 bits. If you choose to encrypt the key (which is probably wise), you'll have to enter the passphrase for it every time you start a server that uses it. This might not be possible; so you might have to opt for an unencrypted key and hope your disk is safe.
Now that you've got a key, you'll need to generate the certificate signing request:
# generate certificate signing request openssl req -new -key privkey.pem -out cert.csr # will ask some questions # CommonName is domain name! # display contents cat cert.csr
The openssl client will ask you some questions about the certificate. Most
of this information is ignored by CAcert.org (see their documentation) but the
CommonName is extremely important: this is where you entered the
fully-qualified domain name of the server you want a certificate for (e.g.
www.mydomain.dom
).
To get a signed certificate from CAcert.org, simply choose Server
certificates -> New and paste in the contents of the
cert.csr
file. You can then copy the signed server certificate
from their website.
Depending on your application, you probably want to store that signed
certificate along with the private key: simply edit the
privkey.pem
file in your favourite text editor and paste the
signed certificate (including the delimiter lines) after the existing private
key. You can then generally point your application at this file and it will be
happy.
A less-well-known but nevertheless useful feature of SSL is that it can be used to authenticate clients to a server, as well as simply providing an encrypted communication channel. Unfortunately, CAcert.org's client certificates can only contain your email address, which can lead to limitations.
To generate a client certificate, you have to add your email address to the CAcert.org site (and of course follow the activation link in the test email). Once this is done, you can simply use the web interface to generate a certificate directly in your browser.
I found that Konqueror (3.5.2) failed to work here. It brought up the client certificate generation dialog etc. but for some reason the process failed. However, Firefox allowed me to generate the client certificate and then export it (they call it "backup") as a PKCS#12 file. I could then import it into Konqueror and it works fine. You can then tell Konqueror to present the client certificate to a specific webserver.
The PKCS#12 certificate can also be used for e.g. subversion clients etc. although this is where the email address becomes a limiting factor.
Although full configuration of Apache's mod_ssl is beyond this page (see the Apache docs, since they're pretty helpful), some tips are in order.
In your vhost configuration (or wherever you put the directive
SSLEngine On
), add the server certificate with the line:
SSLCertificateFile /path/to/cert.pem
This assumes that you've got both the private key and the certificate in the same file. It's also a very good idea to make sure that this f ile is not world-readable. Under Gentoo, the bit of apache that reads the key file runs as root, so I've made it read-only to root with no group or world permissions (0400). If you've encrypted the private key, then apache will pop up with its passphrase dialog; if the key is u nencrypted, this will just work.
You can also configure Apache 2 to verify clients based on their certificates. Again, consult the Apache docs for full details, but an example would be:
SSLVerifyClient require SSLCACertificateFile /usr/share/ca-certificates/cacert.org/cacert.org.crt SSLOptions +FakeBasicAuth AuthName "Tourmaline Server Control" AuthType basic AuthUserFile /var/www/www.lwithers.me.uk/access/site Require valid-user
This tells Apache to accept client certificates signed by the root CA (in
the specified file), and to use the certificate's subject as the username. An
example of the access file /var/www/www.lwithers.me.uk/access/site
might be:
/CN=CAcert WoT User/emailAddress=l@lwithers.me.uk:...
which you would add with the command:
htpasswd2 /passwd/file "/CN=...me.uk"
The password should be set to "password". You can mess around with the directives a little but there's no easy way to convert the horrible mess of a subject into a nice username that something like Subversion could appreciate. What's really needed is an Apache module but nobody has written one.
This is pretty simple; again, you prepare the private key and client
certificate in a .pem
file (should be owned by e.g.
mail:root
and mode 0400). Put this somewhere sensible. Then simply
edit your configuration files to point at this:
TLS_CERTFILE="/path/to/cert.pem"
You can potentially use different keys for the different server components; this is useful if you access the servers on different hostnames (remember: the common name must match the fully-qualified hostname).