github Download
Certificate generation with OpenSSL

Certificate generation with OpenSSL #

Here you will see few tips about how certificates can be generated using openssl CLI tool.

This is more like a collection of tips, and it doesn’t pretend to be exhaustive. In production settings, make sure at least that: your private keys are kept safe; certificate extensions are properly configured; apps that use these certificates are properly configured. A lot of things require attention in order to work as expected and remain secure.

Since there are some parameters we cannot configure with CLI flags, we need to create own configuration file. This is an example of simple openssl.cnf configuration file without intermediate CAs:

# This section is required by OpenSSL, but we specify DN on the command line,
# so here an empty placeholder is used.
[ req ]
distinguished_name = req_dn

[ req_dn ]

# X.509 v3 extensions for issued certificates
[ v3_req ]
basicConstraints = CA:false
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = DNS:localhost

# X.509 v3 extensions for CA certificate
[ v3_ca ]
basicConstraints = critical,CA:true
subjectAltName = DNS:localhost

[ ca ]
default_ca = CA_default

[ CA_default ]
dir = .
database = $dir/index.txt
serial = $dir/serial

certificate = $dir/ca.crt.pem
private_key = $dir/ca.key.pem

default_md = sha256
default_crl_days = 30
policy = policy_anything

[ policy_anything ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

Generate RSA private key #

openssl genrsa -out private_rsa.key.pem 4096

Here 4096 is the key size in bits, other popular choices are 2048 and 3072. It is not recommended using less that 2048 bits due to low security margin of such keys.

Generate EC private key #

openssl ecparam -name prime256v1 -genkey -noout -out private_ec.key.pem

Here prime256v1 is the name of ECC curve to use. Its name also tells about key size in bits (256 here). Run openssl ecparam -list_curves if you need list of all supported curves.

Create self-signed CA certificate #

Here you can use either RSA or EC key for -key flag. EC key is recommended since RSA is kinda outdated nowadays, it has bigger keys while also works slower.

openssl req \
    -x509 -sha256 -nodes -days 365 \
    -key ca.key.pem \
    -out ca.crt.pem \
    -subj '/C=GB/ST=London/L=London/O=Global Security/OU=IT/CN=Test CA'

# Create certificate database, will be needed when signing CSRs
touch index.txt

Show generated certificate in readable format #

openssl x509 -noout -text -in ca.crt.pem

Example output:

        Version: 3 (0x2)
        Serial Number:
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = GB, ST = London, L = London, O = Global Security, OU = IT, CN = Test CA
            Not Before: Jul  5 07:37:16 2021 GMT
            Not After : Jul  5 07:37:16 2022 GMT
        Subject: C = GB, ST = London, L = London, O = Global Security, OU = IT, CN = Test CA
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (4096 bit)
                    ### many lines skipped ###
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Subject Key Identifier:
            X509v3 Authority Key Identifier:

            X509v3 Basic Constraints: critical
    Signature Algorithm: sha256WithRSAEncryption
         ### many lines skipped ###

while using EC key would produce key description like this:

        Signature Algorithm: ecdsa-with-SHA256

        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                ASN1 OID: prime256v1
                NIST CURVE: P-256

    Signature Algorithm: ecdsa-with-SHA256

Create client’s private key #

RSA private key:

openssl genrsa -out cert1.key.pem 4096

EC private key:

openssl ecparam -name prime256v1 -genkey -noout -out cert1.key.pem

Create Certificate Signing Request #

# First, you need a private key called cert1.key.pem,
# use one of command above to generate it

openssl req -new \
    -key cert1.key.pem \
    -out cert1.csr.pem \
    -subj '/C=GB/ST=London/L=London/O=Global Security/OU=IT/CN=Test certificate 1'

Sign Certificate Signing Request #

openssl ca \
    -config openssl.cnf \
    -in cert1.csr.pem \
    -out cert1.crt.pem \
    -extensions v3_req \
    -batch \
    -outdir /tmp \
    -rand_serial \
    -notext \
    -days 365

# See signed certificate being added to database
cat index.txt

Example content of index.txt:

V       220705074134Z           334E651762E338DB251AE2B5E8CF0150D5C8A824        unknown /C=GB/ST=London/L=London/O=Global Security/OU=IT/CN=Test certificate 1

What now?

  • ca.crt.pem is a CA certificate, can be used for options like -tls_ca
  • cert1.crt.pem is a leaf certificate signed by CA itself, can be used for -tls_cert
  • cert1.key.pem is a key corresponding to cert1.crt.pem, can be used for -tls_key

Other useful tools #

If you think using openssl may be complex, you’re not wrong. There is a couple of tools that make life easier when it comes to certificate generation and all this PKI related work.

Two of them are easy-rsa and certstrap.