163

I have a certificate bundle .crt file.

doing openssl x509 -in bundle.crt -text -noout only shows the root certificate.

how do i see all the other certificates?

13 Answers 13

205

http://comments.gmane.org/gmane.comp.encryption.openssl.user/43587 suggests this one-liner:

openssl crl2pkcs7 -nocrl -certfile CHAINED.pem | openssl pkcs7 -print_certs -text -noout

It indeed worked for me, but I don't understand the details so can't say if there are any caveats.

12
  • 15
    This is the best answer - I won't even post my over-kill Python solution! Leave out the "-text" to just get subject/issuer info for each certificate.
    – Chris Wolf
    Mar 28 '16 at 23:03
  • Tried it on /etc/ssl/certs/ca-certificates.crt and got unable to load PKCS7 object
    – OrangeDog
    Jun 30 '17 at 13:48
  • 1
    Isn't this for pkcs7 format, whereas the question is about x509 format bundles? Feb 8 '18 at 2:16
  • 3
    It only uses pkcs7 as intermediate. Input is concatenated PEM. Feb 8 '18 at 7:00
  • 2
    For the benefit of posterity, that's "CRL 2", not "CR 12" -- crl2pkcs7 Dec 3 '19 at 23:01
37

Java's keytool does the trick:

keytool -printcert -v -file <certs.crt>

Annotation: Windows doubleclick does not work. Windows reads only the first certificate in the keystore and automatically extends the trustchain from its built in certificate store.

Results:

  1. All beyond the first certificate in the .crt file are not shown
  2. You may get a different trustchain displayed than you have in the .crt file. This may lead to wrong conclusions.
1
  • Thanks for clarifying the windows thing. This was really confusing the hell out of me Dec 8 '17 at 5:17
22

Following this FAQ led me to this perl script, which very strongly suggests to me that openssl has no native support for handling the nth certificate in a bundle, and that instead we must use some tool to slice-and-dice the input before feeding each certificate to openssl. This perl script, freely adapted from Nick Burch's script linked above, seems to do the job:

#!/usr/bin/perl
# script for splitting multi-cert input into individual certs
# Artistic Licence
#
# v0.0.1         Nick Burch <nick@tirian.magd.ox.ac.uk>
# v0.0.2         Tom Yates <tyates@gatekeeper.ltd.uk>
#

$filename = shift;
unless($filename) {
  die("You must specify a cert file.\n");
}
open INP, "<$filename" or die("Unable to load \"$filename\"\n");

$thisfile = "";

while(<INP>) {
   $thisfile .= $_;
   if($_ =~ /^\-+END(\s\w+)?\sCERTIFICATE\-+$/) {
      print "Found a complete certificate:\n";
      print `echo \'$thisfile\' | openssl x509 -noout -text`;
      $thisfile = "";
   }
}
close INP;
21

Oneliner that displays a summary of every certificate in the file.

openssl crl2pkcs7 -nocrl -certfile CHAINED.pem | openssl pkcs7 -print_certs -noout

(similar to serverfault.com/a/755815/27515 , but this gives shorter output, without the --text option).

example:

$ openssl crl2pkcs7 -nocrl -certfile bundled.crt | openssl pkcs7 -print_certs -noout

subject=/C=NL/postalCode=5705 CN/L=City/street=Example 20/O=Foobar B.V./OU=ICT/OU=Wildcard SSL/CN=*.example.com
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA

subject=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority

subject=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
issuer=/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Roo
3
  • This needs better explanations
    – Sven
    Apr 19 '18 at 9:09
  • 2
    ...such as how this is different from serverfault.com/a/755815/27515
    – larsks
    Oct 8 '20 at 10:20
  • @larsks It's the same except for not having the -text flag. That way it spits out less info (most of which is probably useless to you)
    – JelteF
    Nov 23 '20 at 14:25
5

Since there is no awk based solution:

$ cat ca-bundle | awk '/BEGIN/ { i++; } /BEGIN/, /END/ { print > i ".extracted.crt" }'
$ ls *.extracted.crt | while read cert; do openssl x509 -in $cert -text -noout; done

The first command split bundle into certs by looking for BEGIN, and END lines. The second command loops through the extracted certs and shows them.

2
  • 1
    The print redirection feature in awk is available in gawk and nawk but not in basic awk. And so, this would work on Linux (gawk is linked as awk), but might not on OS X which has basic awk. Nov 9 '15 at 1:34
  • print (and printf) redirection in awk is POSIX, and while I don't have Mac, it works in FreeBSD 10 awk and Solaris 11 both oawk and nawk, as well as GNU awk. But see serverfault.com/a/754668/216633 (and comments) for versions that don't need temp files. Apr 25 at 11:53
4

This may not be pretty, or elegant, but it was quick and worked for me using bash on linux, and PEM formatted blocks in a ca-cert bundle file.

while read line
do
    if [ "${line//END}" != "$line" ]; then
        txt="$txt$line\n"
        printf -- "$txt" | openssl x509 -subject -issuer -noout
        txt=""
    else
        txt="$txt$line\n"
    fi
done < /path/to/bundle/file

You can put it all one line, and adjust the openssl options to suit. I really wish there were a more elegant solution for this, but in this case I think finding the more elegant solution would have taken more time than hacking out the inelegant one.

4
openssl storeutl -noout -text -certs bundle.crt
Paraphrasing from the OpenSSL documentation:

The openssl storeutl app was added in OpenSSL 1.1.1.

The storeutl command can be used to display the contents fetched from the given URIs.

  • -noout prevents output of the PEM data
  • -text prints out the objects in text form, like the -text output from openssl x509
  • -certs Only select the certificates from the given URI
4
  • This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From Review
    – bjoster
    Oct 19 at 13:52
  • 2
    @bjoster, had you tried to run the said command? It seems this answer not only answers the question, it is the most correct answer, shortest, simplest and doing exactly what was asked. Nov 9 at 15:14
  • This should definitely be the answer, though a few extra words describing the solution or demonstrating the solution would help.
    – ruckc
    Nov 9 at 19:37
  • This answer is (technically) on point, but an explanation what it does (and why) would be very helpful.
    – bjoster
    Nov 10 at 13:43
3

In bash usually only one (long) line of code is needed :-)

tfile=$( mktemp -u ) && \
csplit -z -q -f "$tfile" bundle.crt  '/----BEGIN CERTIFICATE-----/' '{*}' && \
find "${tfile%/*}" -name "${tfile##*/}*" -exec openssl x509 -noout -subject -in "{}" \; -delete
2

Try this script: https://github.com/jkolezyn/cert_tree

It prints certificates in a pem bundle as a tree, built based on Subject and Issuer fields.

It prints a tree like this:

cert_tree.py -p ~/.certs/ca_list.pem  
━ CorpRoot            [1]
    ┣━ ServerCA       [2]
    ┣━ example_cert   [3]
    ┗━ example_2      [8]
━ RootCert            [4]
    ┣━ example_cert3  [5] [EXPIRED on: 2019-06-03 13:26:21]
    ┣━ other          [6]
    ┣━ other1         [7] [EXPIRED on: 2017-06-16 21:12:18]
    ┗━ AnotherOne     [9]

cert_tree.py -pe ~/.certs/mycert.pem
━ RootCert                [3] [valid until: 2031-07-08 17:57:15]
    ┗━ IntermediateCert   [2] [valid until: 2023-07-08 18:55:58]
        ┗━ UserCert       [1] [valid until: 2023-09-17 13:33:00]
1

I'd like to throw in the idiomatic perl commandline here:

  perl -ne "\$n++ if /BEGIN/; print if \$n == 1;" mysite.pem

If there's text then a slightly more robust tweak:

 perl -ne "\$n++ if /^-----BEGIN CERTIFICATE-----\$/; print if \$n == 3 && /^-----BEGIN CERTIFICATE-----\$/.../^-----END CERTIFICATE-----\$/;" mysite.pem

Just change the value of what n should be in the second statement to get the nth certificate.

0

Small alteration to MadHatter's post to allow you to copy/paste straight to the CLI. I also included the MD5 hash, which is helpful when making sure the certs are correct. The stdin line returned is the md5 hash of the cert(s).

perl -e 'my $thisfile = "";
foreach (<>) {
   $thisfile .= $_;
   if($_ =~ /^\-+END(\s\w+)?\sCERTIFICATE\-+$/) {
      print "Found a complete certificate:\n";
      print `echo "$thisfile" | openssl x509 -noout -text`;
      print `echo "$thisfile" | openssl x509 -noout -modulus | openssl md5`;
      $thisfile = "";
   }
}' < my_id_cert_and_ca_bundle.crt

If you want to see a nice short concise output you use this version. Helpful if you are only checking that you have included all your cert, but not really checking usage/etc of the cert(s).

perl -e 'my $thisfile = "";
foreach (<>) {
   $thisfile .= $_;
   if($_ =~ /^\-+END(\s\w+)?\sCERTIFICATE\-+$/) {
      print "Found a complete certificate:\n";
      print `echo "$thisfile" | openssl x509 -noout -serial -subject -dates -alias -issuer`;
      print `echo "$thisfile" | openssl x509 -noout -modulus | openssl md5` . "\n";
      $thisfile = "";
   }
}' < my_id_cert_and_ca_bundle.crt

Just in case your openssl version doesn't support all those flags here is some egrep you can use. Same thing as the first one but just pipe to egrep.

perl -e '.....
' < my_id_cert_and_ca_bundle.crt | egrep "Serial|Subject:|Not |Public-Key|^Cert|stdin|ssuer"

To check the MD5 hash of the private key you can do the following.

openssl rsa -noout -modulus -in privateKey.key | openssl md5

Reference: SSL Shopper - Certificate Key Matcher

0

Here's an awk based solution that doesn't rely on intermediate files.

cat bundle.crt | awk '{
  if ($0 == "-----BEGIN CERTIFICATE-----") cert=""
  else if ($0 == "-----END CERTIFICATE-----") print cert
  else cert=cert$0
}' | while read CERT; do
  echo "$CERT" | base64 -d | openssl x509 -inform DER -text -noout
done

It works by reading PEM blocks from stdin and concatenating each block to single base64 encoded line. Lines are then read, decoded and passed to openssl as DER encoded certificates.

2
  • 2
    Just for fun: cat bundle.crt | awk -v cmd="openssl x509 -subject -noout" '/-----BEGIN/ { c = $0; next } c { c = c "\n" $0 } /-----END/ { print c|cmd; close(cmd); c = 0 }'.
    – Manav
    May 30 '16 at 14:11
  • Simpler: awk <bundle.crt -v cmd="openssl x509 -whatever" '/^-----BEGIN/,/^-----END/ {print|cmd} /^-----END/ {close(cmd)}' and if there isn't extraneous material after the last PEM block (or you don't mind a spurious error message) you can omit the first range as well. (@Manav) Apr 25 at 11:48
0

@user1686 suggested another solution in https://superuser.com/questions/1599666/view-all-certs-in-a-pem-cert-file-full-cert-chain-with-openssl-or-another-comm

it is part of the GnuTLS stack.

certtool -i < multiplecerts.pem

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.