Home
Got Linux ?

Blah blah blah... Mostly technical thoughts, rants and gibberish


OpenSSL made easy

[UPDATED 2019.11.03]

OpenSSL can be a very frustrating piece of software, far from the plug'n play ease which modern Infuriating Technologies (IT) have got us accustomed to (with all their nicely preset defaults… and gotchas).

While netsearching immediately reveals quick and dirty howtos for personal use certificates, things get (way!) more complicated when one aims towards setting up a serious Public Key Infrastructure (PKI), even more so when doing so in parallel with the constraints - aka. Certificates Policy and Certification Practice Statement (CP/CPS) - of official Certificate Service Providers (CSP).

In order to overcome this complexity, I’ve come up with a nifty OpenSSL wrapper, which I dubbed OpenSSL-Easy, along sample OpenSSL configurations for the three most common use cases: SSL servers certificates, signature/encryption personal “IDs” and (PAM/Kerberos/Web/VPN/etc.) authentication tokens:

OpenSSL-Easy overview and preliminary setup

While intended to be easy to use interactively (see openssl-easy --help), OpenSSL-Easy can seamlessly be integrated into batch processes, by exporting ad-hoc OPENSSL… environment variables (see the source code).

By default, OpenSSL-Easy does it work in the current directory (OPENSSL_ROOT='.').

The OpenSSL configuration file is expected to be found in this directory (OPENSSL_CONF='./openssl.conf'). Thus, before issuing any OpenSSL-Easy command, one must copy one of the provided sample configuration file into a blank directory and edit it to match one’s identity (company name, country, city, URIs, etc.).

The (CA) private key password can be persisted accross calls thanks to the OPENSSL_PASSWORD (OPENSSL_PASSWORD_CA) variable, which can conventiently set by sourcing the OpenSSL-Easy script:

source openssl-easy set-key-passwd

Options prefixed with the plus sign (+) are specific to OpenSSL-Easy, while options prefixed with the minus sign (-) will be (mostly) passed through to OpenSSL.

All OpenSSL-Easy-generated resources (keys, certs, etc.) are identified by their ID and their creation date:

openssl-easy +id "<resource-id>" [+date "<YYYYMMDD>"] ...

Integration with PKCS#11 is readily achieved thanks to the +pkcs11-... options and corresponding OPENSSL_PKCS11_... variables:

pkcs11-tool --list-token-slots
pkcs11-tool --list-objects --token-label "<token-label>"
openssl-easy +pkcs11-token "<token-label>" +pkcs11-object "<object-label>" ...

Setting up a Certification Authority (CA)

Should you need to setup your own Certification Authority (CA):

openssl-easy make-ca +name "My CA" -days 3650

On the other hand, if you plan to have your certificates signed by an external CA:

openssl-easy make-ca +id 'CA:EXTERNAL'

Server certificate how-to

A server certificate is typically characterized by:

In order to create such a certificate with OpenSSL-Easy:

  1. Use the openssl.server.conf configuration template

  2. Create the private key

    openssl-easy make-key +id '<hostname>'
    openssl-easy show-key +id '<hostname>'  # -noout -text
    
  3. Create the corresponding Certificate Signing Request (CSR)

    openssl-easy make-req +id '<hostname>' +name '<hostname>' \
                          +san-dns '<hostname>'  # +san-dns ...
    openssl-easy show-req +id '<hostname>'  # -noout -text
    
  4. Create the certificate by signing its CSR

    openssl-easy make-cert +id '<hostname>'
    openssl-easy show-cert +id '<hostname>'  # -noout -text
    
  5. OR import the certificate after having its CSR signed by an external CA

    openssl-easy import-cert +id '<hostname>' -in /path/to/certificate.pem
    

Personal certificate how-to

A personal certificate is typically characterized by:

In order to create such a certificate with OpenSSL-Easy:

  1. Use the openssl.personal.conf configuration template

  2. Create the private key

    openssl-easy make-key +id '<email>'
    
  3. Create the corresponding Certificate Signing Request (CSR)

    openssl-easy make-req +id '<email>' +name '<fullname>' +email <email>
    
  4. Create the certificate by signing its CSR

    openssl-easy make-cert +id '<email>'
    
  5. OR import the certificate after having its CSR signed by an external CA

    openssl-easy import-cert +id '<email>' -in /path/to/certificate.pem
    

Authentication certificate how-to

An authentication certificate is typically characterized by:

In order to create such a certificate with OpenSSL-Easy:

  1. Use the openssl.authentication.conf configuration template

  2. Define your Kerberos realm

    export KERBEROS_REALM='EXAMPLE.ORG'
    
  3. Create the private key

    openssl-easy make-key +id '<principal>'
    
  4. Create the corresponding Certificate Signing Request (CSR)

    openssl-easy make-req +id '<principal>' +name '<username>'
    
  5. Create the certificate by signing its CSR; WARNING: make sure to specify the <username> again (required by MIT Kerberos V extensions)

    openssl-easy make-cert +id '<principal>' +name '<username>'
    

You’ll also have to create the certificates for hosts providing/using authentication services:

Certificates Revocation List (CRL) and Online Certificate Status Protocol (OCSP)

To check a CA-signed certificate’s status against its published/embedded CRL Distribution Point:

openssl-easy verify-crl +id ...

To check a CA-signed certificate’s status against its published/embedded OCSP Responder:

openssl-easy verify-oscp +id ...  # -resp_text

Certificates, validity, revocation, etc.

To find out about valid certificates (at a given date):

openssl-easy list-certs  # +date ...

To find out about expired certificates (at a given date):

openssl-easy list-certs +expired  # +date ...

To find out about revoked certificates (at a given date):

openssl-easy list-certs +revoked  # +date ...

The format of the generated Tab-Separated Values (TSV) being:

ID DATE SUBJECT SERIAL STATUS DATE FILE

Setting up a root CA along multiples ICAs

For large deployments, it is recommended setting up a Root Certification Authority (CA), which shall be used - solely! - to sign Intermediate/Issuing Certification Authorities (ICAs) certificates for each purpose (such as the one we covered above).

First, get hold of the ad-hoc OpenSSL configuration file:

Then:

  1. Start by creating the root CA:

    source openssl-easy set-key-passwd  # CA password
    openssl-easy make-ca +name 'My Root CA' -days 3650
    
  2. Then, for each ICA, create its CA-signed certificate:

    source openssl-easy set-key-passwd  # ICA password
    openssl-easy make-key +id 'ICA-<Purpose>'
    openssl-easy make-req +id 'ICA-<Purpose>' +name 'My <Purpose> ICA'
    openssl-easy make-cert +id 'ICA-<Purpose>'
    
  3. Copy the ICA private key and certificate into its own directory:

     mkdir -p /path/to/'ICA-<Purpose>'/CA
     cat keys/'ICA-<Purpose>'-key-*.pem > /path/to/'ICA-<Purpose>'/CA/key.pem
     cat certs/'ICA-<Purpose>'-cert-*.pem > /path/to/'ICA-<Purpose>'/CA/cert.pem
     cat certs/'ICA-<Purpose>'-cert-*.pem > /path/to/'ICA-<Purpose>'/CA/chain.pem
    
  4. Switch to the ICA directory and initialize it:

     cd /path/to/'ICA-<Purpose>'
     openssl-easy make-ca +id 'CA:INTERMEDIATE'
    
  5. Create ICA-signed end-usage certificates

Afterwords: (Extended) Key Usage

One of the common pitfalls that comes with generating your own certificates are their declared (and CA-certified) usage purpose, known as their Key Usage (KU) and Extended Key Usage (EKU), as standardized by RFC 5280

The sample OpenSSL configurations linked above take care of declaring the appropriate (Extended) Key Usage for each use case.

One should note the difference between the keyEncipherment and keyAgreement key usages: