Self-signed multiple-domain SSL certificates

I’ve finally worked out how to create self-signed SSL certificates for multiple domain names with openssl. 

These notes relate to Debian GNU/Linux, but the principles will apply to other operating systems.

The first step to make the process easier and repeatable in the future is to copy the default configuration file from /etc/ssl/openssl.cnf to a working directory where you can adapt it

Let’s assume that you’ve copied /etc/ssl/openssl.cnf to ~/project-openssl.cnf.  Edit the new file and set the various default values to the ones that you need — that’s better than having to respond to openssl’s prompts every time you run it.

For real non-self-signed certificates, you would generate a certificate signing request (.csr) file, ready for a certificate authority to sign it for you.  In that case, you need to follow the instructions at http://wiki.cacert.org/FAQ/subjectAltName.

But for a self-signed certificate, the subjectAltName has to go in a different place.  Make sure you’ve got this line present and un-commented in the [req] section of the config file:

[req]
...
x509_extensions = v3_ca

and then this goes at the end of the [v3_ca] section:

[v3_ca]
...
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com
DNS.2 = www.example.com
DNS.3 = example.co.uk
DNS.4 = www.example.co.uk

There is (apparently) a limit to the number (or total length) of the alternate names, but I didn’t reach it with 11 domain names.

It’s also possible to add IP addresses to the alt_names section like this:

IP.1 = 192.168.1.1
IP.2 = 192.168.69.14

Then to create the key and self-signed certificate, run commands similar to these:

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout project.key -out project.crt -config ~/project-openssl.cnf
cp project.crt /etc/ssl/localcerts/
mv project.key /etc/ssl/private/

Note that I move (rather than copy) the key to the private directory to avoid leaving a copy of it lying around unprotected.

You can check that the certificate contains all the domains that you added by running this:

openssl x509 -in project.crt -text -noout | less

Alternative approach

I haven’t tried this, but according to http://apetec.com/support/GenerateSAN-CSR.htm it’s also possible to create a CSR and then self-sign it like this:

openssl x509 -req -days 3650 -in project.csr -signkey project.key
 -out project.crt v3_req -extfile project-openssl.cnf

References: