Key Knowledge Areas:

  • Understand X.509 certificates, X.509 certificate lifecycle, X.509 certificate fields and X.509v3 certificate extensions
  • Understand trust chains and public key infrastructures, including certificate transparency
  • Generate and manage public and private keys
  • Create, operate and secure a certification authority
  • Request, sign and manage server and client certificates
  • Revoke certificates and certification authorities
  • Basic feature knowledge of Let’s Encrypt, ACME and certbot
  • Basic feature knowledge of CFSSL

Partial list of the used files, terms and utilities:

  • openssl (including relevant subcommands)
  • OpenSSL configuration
  • PEM, DER, PKCS
  • CSR
  • CRL
  • OCSP

Terms

PEM, DER, PKCS

CSR

certificate signing request

CRL

certificate revocation list

OCSP

online certificate status protocol

OCSP stapling

online certificate status protocol stapling

Files

OpenSSL configuration

/etc/pki/tls/openssl.cnf

Utilities

openssl

man 1 ca
man 1 openssl
man 1 genpkey
man 1 pkeyutl
man 1 req

Notes

Certificate Transparency

Certificate Authority

create root certificate:

  • copy and update the configuration file:
    # prepare root directory
    mkdir -p CA/{certs,crl,newcerts,private}
    chmod u=rwx,g=,o= CA/private
    
    # initialize files
    touch CA/index.txt
    printf 1000 > CA/crlnumber
    printf 1000 > CA/serial
    cp /etc/pki/tls/openssl.cnf CA/
    
    # configure file paths
    section="$(sed -n '/^\[ ca \]$/,/\[/ s@^default_ca[ \t]*=[ \t]*@@p' CA/openssl.cnf | sed 's@[ \t]*#.*$@@')"
    sed -e "/^\[ $section \]$/,/^\[/ s@^dir\t\t=.*@dir\t\t= ./CA@" -i CA/openssl.cnf
    sed -e "/^\[ $section \]$/,/^\[/ s@^certificate\t=.*@certificate\t= \$dir/certs/cacert.pem@" -i CA/openssl.cnf
    sed -e "/^\[ $section \]$/,/^\[/ s@^crl\t\t=.*@crl\t\t= \$dir/crl/cacrl.pem@" -i CA/openssl.cnf
    
    # configure defaults for certificates to be issued
    sed -e "/^\[ $section \]$/,/^\[/ s@^x509_extensions\t=.*@x509_extensions\t= v3_intermediate_ca@" -i CA/openssl.cnf
    sed -e "/^\[ $section \]$/,/^\[/ s@^default_days\t=.*@default_days\t= 3650@" -i CA/openssl.cnf
    
    # configure v2 certificate revocation list support
    sed -e "/^\[ $section \]$/,/^\[/ s@^#[ \t]*crl_extensions[ \t]*=.*@crl_extensions\t= crl_ext@" -i CA/openssl.cnf
    
    # configure defaults for root certificate signing request
    sed -e '/^\[ req \]$/,/^\[/ s@^default_bits\t\t=.*@default_bits\t\t= 4096@' -i CA/openssl.cnf
    sed -e '/^\[ req \]$/,/^\[/ s@^default_keyfile[ \t]*=.*@default_keyfile\t= ./CA/private/cakey.pem@' -i CA/openssl.cnf
    sed -e '/^\[ v3_ca \]$/,/^\[/ s@^#[ \t]*keyUsage[ \t]*=.*@keyUsage = cRLSign, keyCertSign@' -i CA/openssl.cnf
    
  • configure CA for signing intermediate:
    cat >> CA/openssl.cnf << EOF
    
    [ v3_intermediate_ca ]
    # Extensions for a typical intermediate CA (man x509v3_config).
    
    # PKIX recommendation.
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid:always,issuer
    basicConstraints = critical,CA:true,pathlen:0
    
    keyUsage = cRLSign, keyCertSign
    
    # CRL and OCSP extensions
    # authorityInfoAccess    = OCSP;URI:http://ocsp.example.net/
    crlDistributionPoints  = URI:http://example.net/cacrl.pem
    EOF
    

    NOTE: basicConstraints = pathlen:0 prevents the issued certificate from issuing another certificate authority

    NOTE: OCSP is being phased out by Let’s Encrypt due to concerns regarding:

    • privacy of end users
    • resource use
    • lack of support in web browsers for OCSP Must Staple extension, which addresses the other two concerns
  • generate the root certificate and private key:
    openssl req -config CA/openssl.cnf -days 7300 -new -newkey rsa -out CA/certs/cacert.pem -subj /C=CY/ST=ProvinceState/L=City/O=Organization/CN=ca-alpha.example.net -x509
    
  • inspect the root certificate:
    openssl x509 -dates -ext basicConstraints -in CA/certs/cacert.pem -issuer -noout -subject
    

create intermediate certificate

  • copy and update the configuration file:
    # prepare intermediate directory
    mkdir -p Intermediate/{certs,crl,csr,newcerts,private}
    chmod u=rwx,g=,o= Intermediate/private
    
    # initialize files
    touch Intermediate/index.txt
    printf 1000 > Intermediate/crlnumber
    printf 1000 > Intermediate/serial
    cp /etc/pki/tls/openssl.cnf Intermediate/
    
    # configure file paths
    section="$(sed -n '/^\[ ca \]$/,/\[/ s@^default_ca[ \t]*=[ \t]*@@p' Intermediate/openssl.cnf | sed 's@[ \t]*#.*$@@')"
    sed -e "/^\[ $section \]$/,/^\[/ s@^dir\t\t=.*@dir\t\t= ./Intermediate@" -i Intermediate/openssl.cnf
    sed -e "/^\[ $section \]$/,/^\[/ s@^certificate\t=.*@certificate\t= \$dir/certs/intermediatecert.pem@" -i Intermediate/openssl.cnf
    sed -e "/^\[ $section \]$/,/^\[/ s@^crl\t\t=.*@crl\t\t= \$dir/crl/intermediatecrl.pem@" -i Intermediate/openssl.cnf
    sed -e "/^\[ $section \]$/,/^\[/ s@^private_key\t=.*@private_key\t= \$dir/private/intermediatekey.pem@" -i Intermediate/openssl.cnf
    
    # configure defaults for certificates to be issued
    sed -e "/^\[ $section \]$/,/^\[/ s@^x509_extensions\t=.*@x509_extensions\t= server_cert@" -i Intermediate/openssl.cnf
    sed -e "/^\[ $section \]$/,/^\[/ s@^#[ \t]*copy_extensions[ \t]*=.*@copy_extensions = copy@" -i Intermediate/openssl.cnf
    sed -e "/^\[ $section \]$/,/^\[/ s@^policy[ \t]*=.*@policy\t\t= policy_anything@" -i Intermediate/openssl.cnf
    
    # configure v2 certificate revocation list support
    sed -e "/^\[ $section \]$/,/^\[/ s@^#[ \t]*crl_extensions[ \t]*=.*@crl_extensions\t= crl_ext@" -i Intermediate/openssl.cnf
    
    
  • configure intermediate for signing server certificates:
    cat >> Intermediate/openssl.cnf << EOF
    
    [ server_cert ]
    # Extensions for server certificates (man x509v3_config).
    
    basicConstraints = CA:FALSE
    nsCertType = server
    nsComment = 'OpenSSL Generated Server Certificate'
    subjectKeyIdentifier = hash
    authorityKeyIdentifier = keyid,issuer:always
    keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
    extendedKeyUsage = serverAuth
    crlDistributionPoints  = URI:http://example.net/intermediatecrl.pem
    EOF
    
  • generate private key:
    openssl genpkey -aes256 -algorithm RSA -out Intermediate/private/intermediatekey.pem -pkeyopt rsa_keygen_bits:4096
    
  • generate certificate signing request:
    openssl req -config Intermediate/openssl.cnf -key Intermediate/private/intermediatekey.pem -new -out Intermediate/csr/intermediatecsr.pem -subj /C=CY/ST=ProvinceState/L=City/O=Organization/CN=intermediate-001.example.net
    
  • inspect the certificate signing request:
    openssl req -in Intermediate/csr/intermediatecsr.pem -noout -text
    
  • sign intermediate certificate:
    openssl ca -batch -config CA/openssl.cnf -extensions v3_intermediate_ca -notext -in Intermediate/csr/intermediatecsr.pem -out Intermediate/certs/intermediatecert.pem
    
  • inspect the intermediate certificate:
    openssl x509 -dates -ext basicConstraints,crlDistributionPoints -in Intermediate/certs/intermediatecert.pem -issuer -noout -subject
    
  • verify the intermediate certificate:
    openssl verify -CAfile CA/certs/cacert.pem Intermediate/certs/intermediatecert.pem
    
  • create certificate chain file:
    cat Intermediate/certs/intermediatecert.pem CA/certs/cacert.pem > Intermediate/certs/ca-chaincert.pem
    

create server certificate

  • copy and update the configuration file:
    # prepare server directory
    mkdir -p Server/{certs,csr,private}
    chmod u=rwx,g=,o= Server/private
    
    # initialize files
    cp /etc/pki/tls/openssl.cnf Server/
    
    # prepare configuration file
    sed -e "/^\[ req \]$/,/^\[/ s@^attributes[ \t]*=.*@# &@" -i Server/openssl.cnf
    
  • generate private key:
    openssl genpkey -algorithm RSA -out Server/private/serverkey.pem -pkeyopt rsa_keygen_bits:2048
    
  • generate certificate signing request:
    openssl req -addext 'subjectAltName = DNS:example.net,DNS:www.example.net,DNS:m.example.net' -config Server/openssl.cnf -key Server/private/serverkey.pem -new -out Server/csr/servercsr.pem -subj /CN=www.example.net
    
  • inspect the certificate signing request:
    openssl req -in Server/csr/servercsr.pem -noout -text
    
  • sign server certificate:
    openssl ca -batch -config Intermediate/openssl.cnf -extensions server_cert -notext -in Server/csr/servercsr.pem -out Server/certs/servercert.pem
    
  • inspect the server certificate:
    openssl x509 -dates -ext basicConstraints,crlDistributionPoints -in Server/certs/servercert.pem -issuer -noout -subject
    
  • verify the server certificate:
    openssl verify -CAfile Intermediate/certs/ca-chaincert.pem Server/certs/servercert.pem
    

operate

root (certificate authority)

  • revoke intermediate certificate:
    openssl ca -config CA/openssl.cnf -revoke Intermediate/certs/intermediatecert.pem
    
  • publish certificate status:
    • generate the CRL:
      openssl ca -config CA/openssl.cnf -gencrl -out CA/crl/cacrl.pem
      
    • inspect the CRL:
      openssl crl -CAfile CA/certs/cacert.pem -in CA/crl/cacrl.pem -noout -text
      
    • verify the CRL:
      openssl crl -CAfile CA/certs/cacert.pem -in CA/crl/cacrl.pem -noout -verify
      
    • host CA/crl/cacrl.pem at the crlDistributionPoints URI configured in CA/openssl.cnf

intermediate

  • revoke server certificate:
    openssl ca -config Intermediate/openssl.cnf -revoke Server/certs/servercert.pem
    
  • publish certificate status:
    • generate the CRL:
      openssl ca -config Intermediate/openssl.cnf -gencrl -out Intermediate/crl/intermediatecrl.pem
      
    • inspect the CRL:
      openssl crl -CAfile Intermediate/certs/intermediatecert.pem -in Intermediate/crl/intermediatecrl.pem -noout -text
      
    • verify the CRL:
      openssl crl -CAfile Intermediate/certs/intermediatecert.pem -in Intermediate/crl/intermediatecrl.pem -noout -verify
      
    • host Intermediate/crl/intermediatecrl.pem at the crlDistributionPoints URI configured in Intermediate/openssl.cnf

secure

  • consider offline root CA
  • consider frequent CRL updates to obviate the need for OCSP

Public and private keys

  • Public key certificate
  • commands:
    • openssl genpkey: generates private key or parameters
    • openssl list -public-key-algorithms: lists supported algorithms
    • openssl pkeyparam: prints and validates parameters
    • openssl pkeyutl: performs low level public key operations (sign data, recover signed data, verify signature, derive shared secret)

parameter generation:

  • valid algorithms: DH, DSA and EC
  • examples:
    • openssl genpkey -genparam -algorithm DH -out dh-params.pem -outform PEM -pkeyopt dh_paramgen_prime_len:2048
    • openssl genpkey -genparam -algorithm DSA -out dsa-params.pem -outform PEM -pkeyopt dsa_paramgen_bits:2048
    • openssl genpkey -genparam -algorithm EC -out ec-params.pem -outform PEM -pkeyopt ec_paramgen_curve:P-256

parameter validation:

  • examples:
    • openssl pkeyparam -check -in dh-params.pem -text
    • openssl pkeyparam -check -in dsa-params.pem -noout
    • openssl pkeyparam -in ec-params.pem -text

Best practices

Howtos