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?
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.
updated june 22:
for openssl 1.1.1 and higher: a single-command answer can be found here serverfault.com/a/1079893 (openssl storeutl -noout -text -certs bundle.crt
)
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:
.crt
file are not shown.crt
file. This may lead to wrong conclusions.Oneliner that displays a summary of every certificate in the file.
openssl crl2pkcs7 -nocrl -certfile CHAINED.pem | openssl pkcs7 -print_certs -noout
It combines all the certificates into a single intermediate PKCS7 file, and then parses the information in each part of that file.
(The same as Beni's answer, 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
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;
openssl storeutl -noout -text -certs bundle.crt
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 URISince 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.
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]
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.
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
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.
@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
awk -v cmd='openssl x509 -noout -text' \
'/BEGIN/{close(cmd)}; {print | cmd}' \
< bundle.pem | less
Or to list only subjects and issuers:
awk -v cmd='openssl x509 -noout -subject -issuer' \
'/BEGIN/{close(cmd)}; {print | cmd}' \
< bundle.pem
The way it works. print
launches cmd
and pipes lines to it one by one until it reaches the /BEGIN/
line. At which point it closes the pipe. The following print
launches another cmd
and starts piping lines to the freshly created pipe.
The credit goes to Stéphane Chazelas.
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
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.