My favorite openssl commands

Intro
openssl is available on almost every operating system. It’s a great tool if you work with certificates regularly, or even occasionally. I want to document some of the commands I use most frequently.

The details

Convert PEM CERTs to other common formats
I just used this one yesterday. I got a certificate in PEM format as is my custom. But not every web server out there is apache or apache-compatible. What to do? I’ve learned to convert the PEM-formatted certificates to other favored formats.

The following worked for a Tomcat server and also for another proprietary web server which was running on a Windows server and wanted a pkcs#12 type certificate:

$ openssl pkcs12 −export −chain −inkey drjohns.key -in drjohns.crt −name “drjohnstechtalk.com” −CAfile intermediate_plus_root.crt −out drjohns.p12

The intermediate_plus_root.crt file contained a concatenation of those CERTs, in PEM format of course.

If you see this error:

Error unable to get issuer certificate getting chain.

it probably means that you forgot to include the root certificate in your intermediate_plus_root.crt file. You need both intermediate plus the root certificates in this file.

The beauty of the above openssl command is that it also takes care of setting up the intermediate CERT – everything needed is shoved into the .p12 file. .p12 can also be called .pfx.

How to examine a pkcs12 (pfx) file

$ openssl pkcs12 ‐info ‐in file_name.pfx
It will prompt you for the password a total of three times!

Examine a certificate

$ openssl x509 −in certificate_name.crt −text

Examine a CSR – certificate signing request

$ openssl req −in certificate_name.csr −text

Examine a private key

$ openssl rsa −in certificate_name.key −text

Create a SAN (subject alternative name) CSR

This is a two-step process. First you create a config file with your alternative names and some other info. Mine, req.conf, looks like this:

[req]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
 
[ dn ]
C=US
ST=New Jersey
CN = drjohnstechtalk.com
 
[ req_ext ]
subjectAltName = @alt_names
 
[ alt_names ]
DNS.1 = drjohnstechtalk.com
DNS.2 = johnstechtalk.com
DNS.3 = www.drjohnstechtalk.com
DNS.4 = www.johnstechtalk.com

Then you run openssl like this, referring to your config file:
$ openssl req −new −nodes −newkey rsa:2048 −keyout mykey.key −out myreq.csr -config req.conf

This creates the private key and CSR in one go. Note that it’s recommended to repeat your common name (CN) in one of the alternative names so that’s what I did.

Let’s examine it to be sure it contains the alternative names:

$ openssl req ‐text ‐in myreq.csr

Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=US, ST=New Jersey, CN=drjohnstechtalk.com
        ...
        Attributes:
        Requested Extensions:
            X509v3 Subject Alternative Name:
                DNS:drjohnstechtalk.com, DNS:johnstechtalk.com, DNS:www.drjohnstechtalk.com, DNS:www.johnstechtalk.com
    Signature Algorithm: sha256WithRSAEncryption
         2a:ea:38:b7:2e:85:6a:d2:cf:3e:28:13:ff:fd:99:05:56:e5:
         ...

Looks good!


Create a simple CSR and private key

$ openssl req −new −nodes −out myreq.csr

This prompts you to enter values for the country code, state and organization name. As a private individual, I am entering drjohnstechtalk.com for organization name – same as my common name. Hopefully this will be accepted.

Look at a certificate and certificate chain of any server running SSL

$ openssl s_client ‐showcerts ‐connect https://host[:port]/

Cool shortcut to fetch certificate from any web server and examine it with one command line

$ echo|openssl s_client ‐connect drjohnstechtalk.com:443|openssl x509 ‐text

Alternate single command line to fetch and examine in one go

$ openssl s_client ‐connect drjohnstechtalk.com:443</dev/null|openssl x509 ‐text

In fact the above commands are so useful to me I invented this bash function to save all that typing. I put this in my ~/.alias file (or .bash_aliases, depending on the OS):

# functions
# to unset a function: unset -f foo; to see the definition: type -a foo
certexamine () { echo|openssl s_client -connect "$@":443|openssl x509 -text|more; }
examinecert () { echo|openssl s_client -connect "$@":443|openssl x509 -text|more; }

Then to examine a certificate I simply type:

$ certexamine drjohnstechtalk.com

Verify your certificate chain of your active server

$ openssl s_client ‐CApath /etc/ssl/certs ‐verify 2 ‐connect drjohnstechtalk.com:443

verify depth is 2
CONNECTED(00000003)
depth=3 /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
verify return:1
depth=2 /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
verify return:1
depth=1 /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
verify return:1
depth=0 /OU=Domain Control Validated/CN=drjohnstechtalk.com
verify return:1
---
Certificate chain
 0 s:/OU=Domain Control Validated/CN=drjohnstechtalk.com
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
   i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
 2 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
   i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
 3 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
   i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFTzCCBDegAwIBAgIJAI0kx/8U6YDkMA0GCSqGSIb3DQEBCwUAMIG0MQswCQYD
VQQGEwJVUzEQMA4GA1UECBMHQXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEa
...
SSL-Session:
    Protocol  : TLSv1
    Cipher    : DHE-RSA-AES128-SHA
    Session-ID: 41E4352D3480CDA5631637D0623F68F5FF0AFD3D1B29DECA10C444F8760984E9
    Session-ID-ctx:
    Master-Key: 3548E268ACF80D84863290E79C502EEB3093EBD9CC935E560FC266EE96CC229F161F5EF55DDF9485A7F1BE6C0BECD7EA
    Key-Arg   : None
    Start Time: 1479238988
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)

Wrong way to verify your certificate chain
When you first start out with the verify sub-command you’ll probably do it wrong. You’ll try something like this:

$ openssl s_client ‐verify 2 ‐connect drjohnstechtalk.com:443

which will produce these results:

verify depth is 2
CONNECTED(00000003)
depth=3 /C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
verify error:num=19:self signed certificate in certificate chain
verify return:0
16697:error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed:s3_clnt.c:983:


Using OCSP

I have had limited success so far to an Online Certificate Status Protocol verification. But I do have something to provide as an example:

$ openssl ocsp ‐issuer cert‐godaddy‐g2.crt ‐cert crt ‐no_nonce ‐no_cert_verify ‐url http://ocsp.godadddy.com/

Response verify OK
crt: good
        This Update: Nov 15 19:56:52 2016 GMT
        Next Update: Nov 17 07:56:52 2016 GMT

Here I’ve stuffed my certificate into a file called crt and stuffed the intermediate certificate into a file called cert-godaddy-g2.crt. How did I know what URL to use? Well, when I examined the certificate file crt it told me:

$ openssl x509 ‐text ‐in crt

...
           Authority Information Access:
                OCSP - URI:http://ocsp.godaddy.com/
...

But I haven’t succeeded running a similar command against certificates used by Google, nor by certificates issued by the CA Globalsign. So I’m clearly missing something there, even though by luck I got the GoDaddy certificate correct.

Generate a simple self-signed certificate
$ openssl req ‐x509 ‐nodes ‐newkey rsa:2048 ‐keyout key.pem ‐out cert.pem ‐days 365

Generating a 2048 bit RSA private key
..........+++
.................+++
writing new private key to 'key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:US
State or Province Name (full name) []:New Jersey
Locality Name (eg, city) [Default City]:.
Organization Name (eg, company) [Default Company Ltd]:.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:drjohnstechtalk.com
Email Address []:

Note that the fields I wished to blank out I put in a “.”

Did I get what I expected? Let’s examine it:

$ openssl x509 ‐text ‐in cert.pem|more

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 16616841832876401013 (0xe69ae19b7172e175)
    Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=US, ST=New Jersey, CN=drjohnstechtalk.com
        Validity
            Not Before: Aug 15 14:11:08 2017 GMT
            Not After : Aug 15 14:11:08 2018 GMT
        Subject: C=US, ST=NJ, CN=drjohnstechtalk.com
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:d4:da:23:34:61:60:f0:57:f0:68:fa:2f:25:17:
...

Hmm. It’s only sha1 which isn’t so great. And there’s no Subject Alternative Name. So it’s not a very good CERT.

Create a better self-signed CERT
$ openssl req ‐x509 ‐sha256 ‐nodes ‐newkey rsa:2048 ‐keyout key.pem ‐out cert.pem ‐days 365

That one is SHA2:

...
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, ST=New Jersey, CN=drjohnstechtalk.com
...

365 days is arbitrary. You can specify a shorter or longer duration.

Then refer to it with a -config argument in your

Listing ciphers
Please see this post.

Fetching the certificates from an SMTP server running TLS

$ openssl s_client −starttls smtp −connect <MAIL_SERVER>:25 −crlf
That’s a good one because it’s hard to do these steps by hand.

Working with Java keytool for Tomcat certificates
This looks really daunting at first. Where do you even start? I recently found the answer. Digicert has a very helpful page which generates the keytool command line you need to crate your CSR and provides lots of installation advice. At first I was skeptical and thought you could not trust a third party to have your private key, but it doesn’t work that way at all. It’s just a complex command-line generator that you plug into your own command line. You know, the whole

$ keytool −genkey −alias drj.com −keyalg RSA -keystore drj.jks −dname=”CN=drj.com, O=johnstechtalk, ST=NJ, C=US” …

Here’s the Digicert command line generator page.

Another good tool that provides a free GUI replacement for the Java command-line utilities keytool, jarsigner and jadtool is Keystore Explorer.

Conclusion
Some useful openssl commands are documented here. A way to grapple with keytool for Tomcat certificates is also shown as a bonus.

References
Digicert’s tool for working with keytool.
GUI replacement for keytool, etc; Keystore Explorer.

This entry was posted in Admin, Security and tagged , , , , , , , , , . Bookmark the permalink.

One Response to My favorite openssl commands

  1. Pingback: The Basics of How to Work with Cipher Settings | Dr John's Tech Talk

Leave a Reply

Your email address will not be published. Required fields are marked *


2 + one =