Generating Keys and Certificates
Certificates are signed by the private keys of another certificate, but how are those certificates signed? By the private keys of yet another certificate! This is the SSL chain of trust: a signed certificate is trusted only if the parent certificate is trusted.
This chain could go on indefinitely, but it has to stop somewhere. The top-level certificate in this chain is the root certificate. This certificate belongs to the certificate authority and is self-signed. The only way to mark this certificate as trusted is to add it explicitly to a (relatively small) list of trusted authorities in the client browser or operating system keychain.
Before we can sign anything with our certificate authority, we must generate a self-signed root certificate. Behind every public certificate is a private key, hence the first task is to generate a new private key for our certificate authority. Even though the key is kept extremely private, it should be encrypted with a strong password for extra security in case the key should fall into the wrong hands. This password will be required to sign any certificate.
The following command generates a new 4096-bit RSA key in private/ca.key.pem encrypted with AES-256 in CBC mode.
$ openssl genrsa -aes256 -out private/ca.key.pem 4096
Available key sizes are:
- 1024 bits insecure,
- 2048 bits (minimum recommended), and
- 4096 bits
Available encryption algorithms include:
- DES in CBC mode broken
- Triple-DES in CBC mode broken
- AES in CBC mode with 128-bit key
- AES in CBC mode with 192-bit key
- AES in CBC mode with 256-bit key
- Camellia cipher in CBC mode with 128-bit key
- Camellia cipher in CBC mode with 192-bit key
- Camellia cipher in CBC mode with 256-bit key
Larger key sizes are more secure. Be sure to use a strong password as well!
Next we create a self-signed X.509 certificate ca.crt.pem that will remain valid for 10 years:
$ openssl req -new \ -config openssl.cnf \ -x509 \ -days 3650 \ -extensions v3_ca \ -key private/ca.key.pem \ -out ca.crt.pem
The -extensions v3_ca flag tells OpenSSL to use the configuration options in the v3_ca section of openssl.cnf. Refer to the setup instructions for details.
Fill out the interactive prompt with your information. Here is an example:
- Pass phrase
- A password that will be required to use the CA key to sign certificate requests.
- Example Company
- Certificate Authority
- Example CA
Congratulations! Now you are ready to start signing certificates.
In the sections that follow, the certificates that are generated will need to be verified by client software such as a browser or email client. This verification process can be checked prior to distributing the certificates with a simple command. To verify the www.example.com.crt.pem certificate against the root certificate (ca.crt.pem), execute:
$ openssl verify -CAfile ca.crt.pem www.example.com.crt.pem
The most common use case for SSL certificates is for use in HTTPS encryption and server identification. First we generate a key, but this key does not need to be encrypted since it must be accessed by a server daemon. Therefore, we can generate both the key and the certificate signing request (CSR) in a single command (the -nodes flag is what tells OpenSSL not to encrypt the generated key):
$ openssl req -new \ -config openssl.cnf \ -nodes \ -keyout private/www.example.com.key.pem \ -out certs/www.example.com.csr.pem
OpenSSL wil ask for information about the organization, but the only vital section is the Common Name field, which must match exactly the domain from which the site will be accessed.
- Example Company
- Web Certificate
Note: If you were acting as a real Certificate Authority for other clients, the key and CSR generation will have been done privately by the client:
$ openssl genrsa -out www.example.com.key.pem 4096 $ openssl req -new \ -key www.example.com.key.pem \ -out www.example.com.csr.pem
The resulting www.example.com.csr.pem would then be submitted for signing. Therefore, if your CA were listed among VeriSign, StartSSL, GeoTrust, etc., you could charge a fee to execute the following command.
Finally, we need to sign the CSR and add the necessary entries in the CA database. OpenSSL takes care of all of this with the following command:
$ openssl ca \ -config openssl.cnf \ -out certs/www.example.com.crt.pem \ -infiles certs/www.example.com.csr.pem
OpenSSL will ask you to verify the information in the CSR and prompt for the root key's password. Now you (or your client) can use the site certificate in certs/www.example.com.crt.pem and the root certificate in ca.crt.pem to secure a site with HTTPS. Here's how to do it in Apache mod_ssl.
A lesser-known feature of SSL is the generation and use of personal keys. Personal keys are most commonly used in enterprise scenarios for client-side authentication for websites and email encryption and signing. First, we need a key and CSR for the user:
$ openssl req -new \ -config openssl.cnf \ -nodes \ -keyout private/client.key.pem \ -out certs/client.csr.pem
Note: Similar to how a site key and CSR would be generated, client keys and CSRs could (and should) be generated by the user:
$ openssl genrsa -out client.key.pem 4096 $ openssl req -new \ -key client.key.pem \ -out client.csr.pem
Next the CSR has to be signed by the certificate authority and added to the CA database, but here we make use of the client_cert configuration options:
$ openssl ca \ -config openssl.cnf \ -extensions client_cert \ -in certs/client.csr.pem \ -out certs/client.crt.pem
The certificate is in certs/client.crt.pem, and the private key (if generated by the CA) is in private/client.key.pem, but many browsers and applications prefer personal keys to be in a PKCS 12 archive. This file contains the client's key, certificate, and root CA certificate.
$ openssl pkcs12 -export \ -in certs/client.crt.pem \ -inkey private/client.key.pem \ -name "Client Personal Certificate" \ -certfile ca.crt.pem \ -out client.p12
This file can now be imported into email clients and web browsers. See the Apache SSL chapter for instructions on setting up client-side authentication in Apache.
In some situations, it may be necessary to mark a certificate as no longer trusted by the root CA. For example, if a key is compromised or if a site has participated in illegal activity. In the client case, this operation is common if an employee no longer works for the corporation but has been issued a certificate for authentication purposes.
To start, the certificate authority needs a place to host a certificate revocation list (CRL). This can be done in the CA base directory. The CA base directory also needs a crlnumber file that operates similarly to the serial number: with every revocation, the crlnumber will be incremented, signifying to clients that subscribe to the CRL that the list has been updated. Be sure to check that this directory and file match what is configured in openssl.cnf.
$ mkdir crl $ echo 1000 > crlnumber
Next we generate a CRL for our CA:
$ openssl ca -gencrl \ -config openssl.cnf \ -out crl/crl.pem
Note: the CRL file can be viewed with the following command:
$ openssl crl -in crl/crl.pem -text
This list is often hosted through an HTTP (or HTTPS) distribution point.
And now the fun part. To revoke a certificate, we first mark the certificate as revoked, and then regenerate the CRL to reflect the updated database state. Suppose that whoever owns the www.example.com.crt.pem certificate has been naughty.
$ openssl ca \ -config openssl.cnf \ -revoke certs/www.example.com.crt.pem $ openssl ca -gencrl \ -config openssl.cnf \ -out crl/crl.pem