Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Using a command line website downloader, such as wget, curl or any other one... In a script...

I have the SHA-1 and the SHA-256 certficate fingerprint of a website. Due to security concerns (1) (2), I don't want to use the public SSL certificate authority system. The fingerprint must be hard coded.

Can a wget like application check the SSL fingerprint?

wget does not have such a functionality. (3)

Using wget --ca-certificate or curl --cacert I would have to run my own local certificate authority, which I'd like to prevent, because that adds a lot complexity. It's also ultra difficult and no one did that ever before. (4)

Isn't there any tool, like
download --tlsv1 --serial-number xx:yy:zz --fingerprint xxyyzz

The solution must of course not be vulnerable to TOCTOU. (5) The MITM could let return a valid fingerprint for the openssl client request and tamper with the following wget request.

share|improve this question
Probably need to do some OpenSSL magic such as:… – Justin Andrusk Jul 30 '12 at 16:32
Visitors: do note that this was cross-posted to the infosec SE. One of the self-answers was copied from there. This is frowned-upon behaviour, btw. – Félix Saparelli Sep 30 '14 at 10:03
up vote 15 down vote accepted


Install required software:

apt-get install ca-certificates curl

Download the public SSL certificate:

openssl s_client -connect -CAfile /usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt >./x.cert </dev/null

Or better:

echo -n | openssl s_client -connect -CAfile /usr/share/ca-certificates/mozilla/DigiCert_Assured_ID_Root_CA.crt | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ./torproject.pem

Get SHA-1 fingerprint:

openssl x509 -noout -in torproject.pem -fingerprint -sha1

Get SHA-256 fingerprint:

openssl x509 -noout -in torproject.pem -fingerprint -sha256

Manually compare SHA-1 and SHA-256 fingerprints with FAQ: SSL.


Optionally render the ca-certificates useless for testing purposes. Using curl here, but wget has a bug Bug and uses the ca-files anyway.

sudo mv /usr/share/ca-certificates /usr/share/ca-certificates_

Download with curl and the pinned certificate:

curl --cacert ./torproject.pem > check.html
share|improve this answer
this doesn't work in the presence of a proxy, though :-/ – Frederick Nord Apr 16 '15 at 9:00

In tcsh:

echo | openssl s_client -connect |& openssl x509 -fingerprint -noout
share|improve this answer
works in zsh, should work for bash too – number5 Jan 22 at 0:22

This is fairly easy to do with the openssl command and its client functionality.

The following little script will take a given domain (no https prefix) and an SHA-1 fingerprint, and exit with no error (0) if the retrieved fingerprint matches, but with exit code 1 if there is no match. You can then incorporate it into your script by simply testing the last exit code $?:

FPRINT=`echo -n | openssl s_client -connect $1:443 2>/dev/null \| openssl x509 -noout -fingerprint | cut -f2 -d'='` if [ "$2" = "$FPRINT" ]; then exit 0 else exit 1 fi
share|improve this answer
It's vulnerable to TOCTOU. [1] The MITM could let return a valid fingerprint for the openssl client request and tamper with the following wget request. [1] – James Mitch Sep 14 '12 at 11:30
True, in theory. It would be fairly easy to modify wget and compile it with OpenSSL so that it performs what you want inline, but that is beyond the scope of an AU answer. – izx Sep 14 '12 at 12:19
So, how about using s_client to also retrieve the document? Something like (echo -ne "Host: ${HOST}\n\rGET ${URL}\n\r" && yes) 2>/dev/null | openssl s_client -connect ${HOST}:443 should work, no? Well, you have to split the SSL session info from the actual content reply. – taneli Sep 17 '12 at 11:10


# Code snippets taken from Net::SSLeay documentation and mildly modified.
# Requires a newer version of SSLeay (tested with 1.48)
# Needless to say, verify correct $host and $fingerprint before testing!!!

use Net::SSLeay qw(get_https3);

$host = "";
$port = 443;
$fingerprint = "C1:95:6D:C8:A7:DF:B2:A5:A5:69:34:DA:09:77:8E:3A:11:02:33:58";

($p, $resp, $hdrs, $server_cert) = get_https3($host, $port, '/');
if (!defined($server_cert) || ($server_cert == 0)) {
    warn "Subject Name: undefined, Issuer  Name: undefined";
} elsif (Net::SSLeay::X509_get_fingerprint($server_cert, "sha1") ne $fingerprint) {
    warn 'Invalid certificate fingerprint '
        .  Net::SSLeay::X509_get_fingerprint($server_cert, "sha1")
        . ' for ' . Net::SSLeay::X509_NAME_oneline(
} else {
    print $p;

As is outlined in the Net::SSLeay documentation, this method means verification after the HTTP transaction, and so should not be used if you want to verify you're talking to the right server before sending them data. But if all you're doing is deciding whether or not to trust what you just downloaded (which is sounds like you are from your reference #4) this is fine.

share|improve this answer

This is also enough:

openssl x509 -fingerprint -in server.crt
share|improve this answer

That's my everyday script:

curl --insecure -v 2>&1 | awk 'BEGIN { cert=0 } /^\* Server certificate:/ { cert=1 } /^\*/ { if (cert) print }'


* Server certificate:
*    subject: C=US; ST=California; L=Mountain View; O=Google Inc;
*    start date: 2016-01-07 11:34:33 GMT
*    expire date: 2016-04-06 00:00:00 GMT
*    issuer: C=US; O=Google Inc; CN=Google Internet Authority G2
*    SSL certificate verify ok.
* Server GFE/2.0 is not blacklisted
* Connection #0 to host left intact
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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