The Hitchhiker's Guide to Using OpenSSL for Managing Certificates

Introduction

Over the years I have had to do a lot of repetitive tasks in OpenSSL, and I've always had to hunt down what command I needed to use. So, I finally made a list of the most common use cases and commands, and now it's time to share.

A Word About Certificate Formats and Encoding

There are two main types of encoding of certificates; DER and PEM.

DER is a binary encoding of a certificate. Typically these use the file extension of .crt or .cer.

PEM is a Base64 encoding of a certificate represented in ASCII therefore it is readable as a block of text. This is very useful as you can open it in a text editor work with the data more easily. The data itself is contained between a prefix of:

-----BEGIN CERTIFICATE-----

and a postfix of:

-----END CERTIFICATE-----

Similarly, RSA keys have a prefix and postfix as well. They are denoted with:

-----BEGIN PRIVATE KEY-----

and

-----END PRIVATE KEY-----

Certificate Signing Requests use:

-----BEGIN CERTIFICATE REQUEST-----

and

-----END CERTIFICATE REQUEST-----

Typically these use the file extension of .pem. RSA private and public keys use the file extension of .key. Certificate Signing Requests (CSRs) use the file extension of .csr.

In the event that you are getting errors when running any OpenSSL commands, you may need to explicitly declare the input format and/or the output format. This can be done by adding the following flags to almost any command:

-inform <pem|der> and -outform <pem|der>

Creating an RSA Private Key

Create a 2048 bit RSA private key that is unencrypted:

openssl genrsa -out name.unencrypted.priv.key 2048

Create a 2048 bit RSA private key that is encrypted with 3DES:

openssl genrsa -des3 -out name.encrypted.priv.key 2048

Encrypting/Decrypting an RSA Private Key

Encrypt an RSA private key with 3DES:

openssl rsa -des3 -in name.unencrypted.priv.key -out name.encrypted.priv.key

Decrypt an RSA private key:

openssl rsa -in name.encrypted.priv.key -out name.unencrypted.priv.key

Creating a Certificate Signing Request

Create a CSR for an existing private key:

openssl req -new -key name.<en|unen>crypted.priv.key -out name.csr

Create a CSR based on a previously issued certificate:

openssl x509 -x509toreq -in name.cer -signkey name.<en|unen>crypted.priv.key -out name.csr

Create an unencrypted private key and CSR in one command:

openssl req -new -newkey rsa:2048 -nodes -keyout name.unencrypted.priv.key -out name.csr

Create an encrypted private key and CSR in one command:

openssl req -new -newkey rsa:2048 -keyout name.encrypted.priv.key -out name.csr

Create a CSR using SHA256 signing algorithm instead of the default SHA1:

openssl req -new -newkey rsa:2048 -sha256 -nodes -keyout name.unencrypted.priv.key -out name.csr

Creating Certificate Signing Requests with Subject Alternate Names

Creating a CSR with Subject Alternate Names (SANs) requires creating a configuration file with the specifics. Then you call it with OpenSSL.

Create a file, name.req.config:

[ req ]
default_bits        = 2048
distinguished_name  = req_distinguished_name
req_extensions     = req_ext

[ req_distinguished_name ]
countryName           = Country Name (2 letter code)
countryName_default   = US
stateOrProvinceName   = State or Province Name (full name)
stateOrProvinceName_default = Florida
localityName          = Locality Name (eg, city)
localityName_default  = Tampa
organizationName          = Organization Name (eg, company)
organizationName_default  = Acme Corporation
commonName            = Common Name (eg, YOUR name)
commonName_max        = 64

[ req_ext ]
subjectAltName          = @alt_names

[alt_names]
DNS.1   = host1.domain.com
DNS.2   = host2.domain.com
DNS.3   = host3.domain.com
DNS.4   = host.differentdomain.com

Create the CSR by referencing the above configuration file:

openssl req -new -key name.encrypted.priv.key -config name.req.config -out name.csr

Showing Contents of Certificate Signing Requests

Print out the contents of the CSR in human-readable format:

openssl req -in name.csr -noout -text

Showing Contents of Certificates

Print out the contents of the certificate in human-readable format:

openssl x509 -in name.pem -noout -text

Verifying Association of Private Key to Certificate

To compare whether a private key and certificate match you need to compare the modulus of both. Considering these are very long strings of text and numbers, it's easier to perform an MD5 checksum and compare the hashes.

Output the modulus MD5 hash of the certificate:

openssl x509 -noout -modulus -in name.pem | openssl md5

Output the modulus MD5 hash of the private key:

openssl rsa -noout -modulus -in name.<en|unen>crypted.priv.key | openssl md5

Compare the outputs to make sure the MD5 hashes match.

Bash one-liner:

For unencrypted private key:

diff -q -s <(openssl x509 -noout -modulus -in name.pem | openssl md5) <(openssl rsa -noout -modulus -in name.unencrypted.priv.key | openssl md5)

For encrypted private key:

diff -q -s <(openssl x509 -noout -modulus -in name.pem | openssl md5) <(openssl rsa -noout -modulus -in name.encrypted.priv.key -passin pass:SuperSecretPassword | openssl md5)

The above command will show Files /dev/fd/63 and /dev/fd/62 are identical if the MD5 hashes match, and will show Files /dev/fd/63 and /dev/fd/62 differ if the MD5 hashes are different.

Combining Root CA and Intermediate CA Certificates into One File

In order to work with certificates that have more than one CA certificate in the issuance path, you have to combine all of the certificates into one single file. Most certificates will be issued by an intermediate authority, and then that intermediate will have been issued by a root authority.

To combine multiple PEM certificates, you just need to put the ASCII data from all of the certificates into one file. Below is an example of this.

EDIT: Reddit user zerouid mentioned that the order of the PEM certificates in the file matters for some older versions of Java. So, to be on the safe side make sure to put the key first (when applicable), then the certificate, then the intermediate, and finally the root certificate. Basically work your way up the chain to the root certificate.

-----BEGIN CERTIFICATE-----
MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY28ycC4gYnkgcmVmLiAobGltaXRzIGxp
YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
fF6adulZkMV8gzURZVE=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE9TCCA92gAwIBAgIETA6MOTANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw1xMTExMTExNTQwNDBaFw0yMTEx
MTIwMjUxMTdaMIGxMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5j
LjE5MDcGA1UECxMwd3d3LmVudHJ1c3QubmV0L3JwYSBpcyBpbmNvcnBvcmF0ZWQg
YnkgcmVmZXJlbmNlMR8wHQYDVQQLExYoYykgMjAwOSBFbnRydXN0LCBJbmMuMS4w
LAYDVQQDEyVFbnRydXN0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gTDFDMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl6MtPJ7eBdoTwhGNnY7jf8dL
flqfs/9iq3PIKGu6EGSChxPNVxj/KM7A5g4GkVApg9Hywyrb2NtOBMwA64u2lty8
qvpSdwTB2xnkrpz9PIsD7028GgNl+cGxP3KG8jiqGa4QiHgo2nXDPQKCApy5wWV3
diRMmPdtMTj72/7bNwJ2oRiXpszeIAlJNiRpQvbkN2LxWW2pPO00nKOO29w61/cK
b+8u2NWTWnrtCElo4kHjWpDBhlX8UUOd4LLEZ7TLMjEl8FSfS9Fv29Td/K9ebHiQ
ld7KOki5eTybGdZ1BaD5iNfB6KUJ5BoV3IcjqrJ1jGMlh9j4PabCzGb/pWZoVQID
AQABo4IBDjCCAQowDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAw
MwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5lbnRydXN0
Lm5ldDAyBgNVHR8EKzApMCegJaAjhiFodHRwOi8vY3JsLmVudHJ1c3QubmV0LzIw
NDhjYS5jcmwwOwYDVR0gBDQwMjAwBgRVHSAAMCgwJgYIKwYBBQUHAgEWGmh0dHA6
Ly93d3cuZW50cnVzdC5uZXQvcnBhMB0GA1UdDgQWBBQe8auJBvhJDwEzd+4Ueu4Z
fJMoTTAfBgNVHSMEGDAWgBRV5IHREYC+2Im5CKMx+aEkCRa5cDANBgkqhkiG9w0B
AQUFAAOCAQEAQJqHfojUzCanS/p4SiDV+aI2IbvuW6BPRI3PqvmXF5aEqchnm7vm
EN551lZqpHgUSdl87TBeaeptJEZaiDQ9JifPaUGEHATaGTgu24lBOX5lH51aOszh
DEw3oc5gk6i1jMo/uitdTBuBiXrKNjCc/4Tj/jrx93lxybXTMwPKd86wuinSNF1z
/6T98iW4NUV5eh+Xrsm+CmiEmXQ5qE56JvXN3iXiN4VlB6fKxQW3EzgNLfBtGc7e
mWEn7kVuxzn/9sWL4Mt8ih7VegcxKlJcOlAZOKlE+jyoz+95nWrZ5S6hjyko1+yq
wfsm5p9GJKaxB825DOgNghYAHZaS/KYIoA==
-----END CERTIFICATE-----

Verifying Validity of Certificate Chain

Verify validity of certificate for sslserver usage:

openssl verify -verbose -purpose sslserver -CAfile CAchain.pem name.pem

Combining Private Key, Certificate, and CA Chain into a PFX

Combine into PFX:

openssl pkcs12 -export -out name.pfx -inkey name.<en|unen>crypted.priv.key -in name.pem -certfile CAchain.pem

Breaking Apart a PFX into Private Key, Certificate, and CA Chain

Extract Private Key

Extract encrypted private key:

openssl pkcs12 -in name.pfx -nocerts -out name.encrypted.priv.key

Extract unencrypted private key:

openssl pkcs12 -in name.pfx -nocerts -nodes -out name.unencrypted.priv.key

Extract Certificate

Extract only the certificate:

openssl pkcs12 -in name.pfx -nokeys -clcerts -out name.pem

Extract Certificate Authority Chain

Extract CA chain. If there are multiple certificates in the chain, they will all be in the same output file.

openssl pkcs12 -in name.pfx -nokeys -cacerts -out CAchain.pem

Converting To/From PEM & DER

Convert from PEM to DER:

openssl x509 -in name.pem -inform pem -out name.cer -outform der

Convert from DER to PEM:

openssl x509 -in name.cer -inform der -out name.pem -outform pem