Creating SSL Certificates

Generating an RSA key with OpenSSL:

cd /etc/ssl/private
openssl genrsa -des3 -out private-key.pem 2048
chmod 600 private-key.pem

* Note: Remove the -des3 from the command line if you do not wish to have a passphrase or be asked for one if you are using this key with a webserver

Remember to ensure that you keep the private.key file, well, private. If someone was able to obtain the private key and the certificate issued by the certificate authority, they can in effect have a valid SSL setup (if other criteria is corrent) and look as legitimate as your SSL site setup.

Real world certificates are pretty cheap these days so it is recommended that you use one instead of a self-signed so there are no browser issues when you go to your new site that uses SSL

To create a Certificate Signing Request (CSR) with OpenSSL, you’ll need the key that you produced above.

cd /etc/ssl
openssl req -new -newkey rsa:2048 -nodes -keyout private/private-key.pem -out certificate-request.csr -subj /CN=my.domain.name

You’ll then need to upload the contents of the CSR file to your certificate provider or email it to them for processing.

While you are waiting for the confirmation and/or the new shiny certificate to arrive, we should make a strong Ephemeral Diffie-Hellman (DHE) key to use with the TLS installation.  The default used (with OpenSSL anyway) is 1024 bit key which is weaker than the certificate we will be issued.  This needs to be higher bit key than the certificate issued as Diffie-Hellman (DH) clients will be using a weaker key-exchange non-ephemeral DH clients:

openssl dhparam -out dhparam.dhpem 4096

When you get the signed certificate returned to you, you’ll need to add it into your webserver configuration file. Below is what would be needed in the ‘server’ block for Nginx:

ssl on;
ssl_certificate /etc/ssl/signed-certificate.crt;
ssl_certificate_key /etc/ssl/private/private-key.pem;
ssl_dhparam /etc/ssl/private/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:!aNULL:!MD5;
ssl_prefer_server_ciphers off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=15552000" always;

I’d suggest using something more informative for file names in the examples that were used above so you can easily identify what key belongs to what certificate:

shop.example.com.pem – The private key for the host shop.example.com
shop.example.com.csr – The certificate signing request for shop.example.com
shop.example.com.crt – The issued certificate for host shop.example.com
shop.example.com.dhpem – The Ephemeral Diffie-Hellman 4096-bit key for host shop.example.com

In most cases, you’ll need to append your SSL providers Intermediate CA Bundle to your .crt file.  Step 2 and step 3 on the RapidSSL site sums up how this is done for Nginx quite well.

Further How-To information on creating SSL certificates, including information if you do wish to make self-signed certificates can be found at the OpenSSL website

Edit 12/10/2022: This page was originally written on 15/3/2013. Updates have been made to the Nginx config and the certificate request sections to reflect modern commands and a more secure configuration.