Verify a certificate chain using openssl verify
If a certificate is found which is its own issuer it is assumed to be the root CA.
In other words, root CA needs to be self signed for verify to work. This is why your second command didn’t work. Try this instead:
openssl verify -CAfile RootCert.pem -untrusted Intermediate.pem UserCert.pem
It will verify your entire chain in a single command.
I’m up-voting this answer as I recently had to do this and after trying different options listed by man verify , I found that the -untrusted parameter is the correct one to use when specifying the intermediate certificate.
I think the second answer: stackoverflow.com/a/31205833/173062 is more accurate — it passes the chain of certificates to the -CAfile parameter.
-untrusted doesn’t check whether certificate chain is fully valid. Please consider to pass both intermediate and root to command as -CAfile as other questions suggests.
Use -untrusted for Intermediate.pem if it is possible that the following happens: mail.python.org/pipermail/cryptography-dev/2016-August/…
That’s not what OP asked for, but in case you want to verify NOT self-signed chain, then use system/browser CA file instead of your own. For example on OS X with openssl from homebrew use: openssl verify -CAfile /usr/local/etc/openssl/cert.pem -untrusted Intermediate.pem UserCert.pem
That’s one of the few legitimate jobs for cat :
openssl verify -verbose -CAfile <(cat Intermediate.pem RootCert.pem) UserCert.pem
As Greg Smethells points out in the comments, this command implicitly trusts Intermediate.pem. I recommend reading the first part of the post Greg references (the second part is specifically about pyOpenSSL and not relevant to this question).
In case the post goes away I'll quote the important paragraphs:
Unfortunately, an "intermediate" cert that is actually a root / self-signed will be treated as a trusted CA when using the recommended command given above:
$ openssl verify -CAfile <(cat geotrust_global_ca.pem rogue_ca.pem) fake_sometechcompany_from_rogue_ca.com.pem fake_sometechcompany_from_rogue_ca.com.pem: OK
It seems openssl will stop verifying the chain as soon as a root certificate is encountered, which may also be Intermediate.pem if it is self-signed. In that case RootCert.pem is not considered. So make sure that Intermediate.pem is coming from a trusted source before relying on the command above.
WARNING: do NOT use this if Intermediate.pem is at all untrusted. For more info read here: mail.python.org/pipermail/cryptography-dev/2016-August/…
Thanks for pointing that out, Greg. When I gave the answer, I downloaded both roots and intermediates from the issuers' homepages, so the thought didn't occur to me. I have updated the answer to make clear that the intermediate is implictly trusted with this command.
@somenickname, see Tony's comment. The -untrusted option is preferable anyway. I suggest you ask your own question if you want further help. Comments aren't the right place to debug your problem.
How can an "intermediate" cert be self-signed? If it's a self-signed CA, surely it's a root cert, not an intermediate cert. As such, unless I miss something, using it as a CAfile (trusted) should mean it's trusted [feature], using it as an intermediate (untrusted) should have no effect because the cert that proves it is OK is itself [not a bug].
The problem is, that openssl -verify does not do the job.
As Priyadi mentioned, openssl -verify stops at the first self signed certificate, hence you do not really verify the chain, as often the intermediate cert is self-signed.
I assume that you want to be 101% sure, that the certificate files are correct before you try to install them in the productive web service. This recipe here performs exactly this pre-flight-check.
Please note that the answer of Peter is correct, however the output of openssl -verify is no clue that everything really works afterwards. Yes, it might find some problems, but quite not all.
Here is a script which does the job to verify a certificate chain before you install it into Apache. Perhaps this can be enhanced with some of the more mystic OpenSSL magic, but I am no OpenSSL guru and following works:
#!/bin/bash # This Works is placed under the terms of the Copyright Less License, # see file COPYRIGHT.CLL. USE AT OWN RISK, ABSOLUTELY NO WARRANTY. # # COPYRIGHT.CLL can be found at http://permalink.de/tino/cll # (CLL is CC0 as long as not covered by any Copyright) OOPS() < echo "OOPS: $*" >&2; exit 23; > PID= kick() < [ -n "$PID" ] && kill "$PID" && sleep .2; PID=; >trap 'kick' 0 serve() < kick PID= openssl s_server -key "$KEY" -cert "$CRT" "$@" -www & PID=$! sleep .5 # give it time to startup >check() < while read -r line do case "$line" in 'Verify return code: 0 (ok)') return 0;; 'Verify return code: '*) return 1;; # *) echo ". $line . ";; esac done < <(echo | openssl s_client -verify 8 -CApath /etc/ssl/certs/) OOPS "Something failed, verification output not found!" return 2 >ARG="$" KEY="$ARG.key" CRT="$ARG.crt" BND="$ARG.bundle" for a in "$KEY" "$CRT" "$BND" do [ -s "$a" ] || OOPS "missing $a" done serve check && echo ". =========> CA-Bundle is not needed! something is wrong, verification failed!
Note that the output after EVERYTHING OK is the Apache setting, because people using NginX or haproxy usually can read and understand this perfectly, too 😉
There is a GitHub Gist of this which might have some updates
Prerequisites of this script:
- You have the trusted CA root data in /etc/ssl/certs as usual for example on Ubuntu
- Create a directory DIR where you store 3 files:
- DIR/certificate.crt which contains the certificate
- DIR/certificate.key which contains the secret key for your webservice (without passphrase)
- DIR/certificate.bundle which contains the CA-Bundle. On how to prepare the bundle, see below.
How to create the certificate.bundle file?
In the WWW the trust chain usually looks like this:
- trusted certificate from /etc/ssl/certs
- unknown intermediate certificate(s), possibly cross signed by another CA
- your certificate ( certificate.crt )
Now, the evaluation takes place from bottom to top, this means, first, your certificate is read, then the unknown intermediate certificate is needed, then perhaps the cross-signing-certificate and then /etc/ssl/certs is consulted to find the proper trusted certificate.
The ca-bundle must be made up in excactly the right processing order, this means, the first needed certificate (the intermediate certificate which signs your certificate) comes first in the bundle. Then the cross-signing-cert is needed.
Usually your CA (the authority who signed your certificate) will provide such a proper ca-bundle-file already. If not, you need to pick all the needed intermediate certificates and cat them together into a single file (on Unix). On Windows you can just open a text editor (like notepad.exe ) and paste the certificates into the file, the first needed on top and following the others.
There is another thing. The files need to be in PEM format. Some CAs issue DER (a binary) format. PEM is easy to spot: It is ASCII readable. For mor on how to convert something into PEM, see How to convert .crt to .pem and follow the yellow brick road.
- intermediate2.crt the intermediate cert which signed your certificate.crt
- intermediate1.crt another intermediate cert, which singed intermediate2.crt
- crossigned.crt which is a cross signing certificate from another CA, which signed intermediate1.crt
- crossintermediate.crt which is another intermediate from the other CA which signed crossigned.crt (you probably will never ever see such a thing)
Then the proper cat would look like this:
cat intermediate2.crt intermediate1.crt crossigned.crt crossintermediate.crt > certificate.bundle
And how can you find out which files are needed or not and in which sequence?
Well, experiment, until the check tells you everything is OK. It is like a computer puzzle game to solve the riddle. Every. Single. Time. Even for pros. But you will get better each time you need to do this. So you are definitively not alone with all that pain. It's SSL, ya' know? SSL is probably one of the worst designs I ever saw in over 30 years of professional system administration. Ever wondered why crypto has not become mainstream in the last 30 years? That's why. 'nuff said.