(re)generate self-signed SSL certificate for apache

… using genkey utility if your system has it or the do-it-yourself generic way.

genkey

genkey is a dialog(1) (interactive) script that generates SSL certificates:

root# genkey
Usage: genkey [options] servername
    --test   Test mode, skip random data creation, overwrite existing key
    --genreq Just generate a CSR from an existing key
    --makeca Generate a private CA key instead
    --days   Days until expiry of self-signed certificate (default 30)

Notice the default of 30 days. It won’t overwrite any existing keys, it will produce an error and exit, so you need to delete/move them by hand.

root# genkey --days 365 `hostname`
  1. Next
  2. select key strength (1024) -> Next
  3. wait
  4. faceroll the keyboard while performing the sacrifice of a random bit for better entropy
  5. No (unless Yes, but No)
  6. type in your company’s data, make sure ‘common name’ is the fully qualified domain name for the server you intend to use this on
  7. do NOT encrypt the passphrase. if you do encrypt it you’ll have to type in the password every time you start apache. People don’t usually want that.
  8. keep a moment of silence for the random bit you had to lose in the name of privacy and security. unless it’s a pink bit. damn racist

Certificate is generated, get it into apache.

The generic way

  • Generate private key

    root# openssl genrsa -des3 -out server.key 1024
    Generating RSA private key, 1024 bit long modulus
    ........++++++
    ...........++++++
    e is 65537 (0x10001)
    Enter pass phrase for server.key:
    Verifying - Enter pass phrase for server.key:

    1024 bit, triple-des encrypted. You have to enter a passphrase, but it gets removed. Do remember it.

  • Remove the pass phrase

    root# mv server.key server.key.encrypted
    root# openssl rsa -in server.key.encrypted -out server.key
    Enter pass phrase for server.key.encrypted:
    writing RSA key
    root# cat server.key server.key.encrypted 
  • Generate a certificate signing request

    This request gets sent to a signing authority, like VeriSign, or you can sign it yourself. VeriSign-like people are supposed to check that you are indeed who you say you are and sign the certificate so that other people can verify they are not talking to someone else. This would provide communication encryption and identity verification. With a self-signed certificate all you really get is communication encryption, but that’s good enough for most.

    root# openssl req -new -key server.key -out server.csr
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter '.', the field will be left blank.
    -----
    Country Name (2 letter code) [GB]:RO
    State or Province Name (full name) [Berkshire]:Judet
    Locality Name (eg, city) [Newbury]:Localitate
    Organization Name (eg, company) [My Company Ltd]:Neant
    Organizational Unit Name (eg, section) []:webserver
    Common Name (eg, your name or your server's hostname) []:www.neant.ro
    Email Address []:rootneantro
        
    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    root# cat server.csr
  • Sign the certificate

    Obviously, you don’t need to do this if VeriSign-like is going to. But you still can, and use this certificate while VeriSign-like is signing the real one. The -days parameter says how long you want the certificate to be valid.

    root# openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
    Signature ok
    subject=/C=RO/ST=Judet/L=Localitate/O=Neant/OU=webserver/CN=www.neant.ro/emailAddress=rootneantro
    Getting Private key
    root# cat server.crt

All good, now get it into apache. Oh, make damn sure no one but root can read the private key files.

Resigning a certificate

Just in case it’s not clear, when a certificate expires you don’t need to regenerate the key, although it might be a good idea for a self-signed cert. Just make a new signing request and sign that one again. In the case of a CentOS 5 server:

root# openssl req -new -key /etc/httpd/conf/ssl.key/server.key -out /etc/httpd/conf/ssl.csr/server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [GB]:RO
State or Province Name (full name) [Berkshire]:Judet
Locality Name (eg, city) [Newbury]:Localitate
Organization Name (eg, company) [My Company Ltd]:Neant
Organizational Unit Name (eg, section) []:www
Common Name (eg, your name or your server's hostname) []:www.neant.ro
Email Address []:rootneantro

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
root# openssl x509 -req -days 365 -in /etc/httpd/conf/ssl.csr/server.csr -signkey /etc/httpd/conf/ssl.key/server.key -out /etc/httpd/conf/ssl.crt/server.crt 
Signature ok
subject=/C=RO/ST=Judet/L=Localitate/O=Neant/OU=www/CN=www.neant.ro/emailAddress=rootneantro
Getting Private key
root# /etc/init.d/httpd graceful
root#

Apache mod_ssl config

These lines need to be present in the host’s http conf and point to the right files, obviously. In case of resigning, specially if there are multiple vhosts on the server, check where the original key and certificate files are.

SSLEngine on
SSLCertificateFile /usr/local/apache/conf/ssl.crt/server.crt
SSLCertificateKeyFile /usr/local/apache/conf/ssl.key/server.key