6

If I have downloaded a file from the internet, and the source website has provided a checksum or hash (eg. SHA-256), how do I verify that the hash of the downloaded file matches the hash reported on the site?

For example, I’ve downloaded a file, and the website states that the SHA-256 hash for it is:

d9cd63f187db2daea1371289508c63a7a24c46316f15ac61f030a7d6ea423915

I do know how to create an SHA-256 hash of the downloaded file using:

shasum -a 256 /path/to/downloaded.pkg

However, I don’t want to do a manual, a.k.a. eyeball, check of the hash. Instead I want to compare the two hashes using a command like diff, preferably by executing a single command-line.

3
  • 1
    If it's just for a file once in a while, why not simply copy the checksum from the website (to the clipboard), then simply do a ⌘+F in the Terminal window? – Daze Apr 21 '20 at 14:16
  • Perhaps I’m missing something, but doesn’t ⌘+F just find a matching string if that string (eg. the checksum) happens to show up in the visible terminal history? – TransferOrbit Apr 21 '20 at 15:22
  • 1
    Exactly. Run your command in the Terminal window to calculate the hash of your file. Then do ⌘+F in the Terminal window and if the checksum matches, it will get highlighted. If I'm not making sense, then I haven't understood your question correctly. – Daze Apr 21 '20 at 20:10
3

You have already received answers on how to do an automatised comparison of the two hash values to ensure they are completely alike. I just wanted to add a different angle on how to compare the hash values.

Actually it is in almost any case enough to to an "eyeball comparison". I.e. if you check that first few characters and the last few characters are the same, and it "looks the same" - then this is a really good verification.

If you're trying to do an automatised comparison "by heart", there's a risk that you accidentally enter the wrong command line or somehow subtly alter the meaning of the command.

The alternative to doing it by heart is to spend time finding and cutting-pasting the script/command line every time you need to check. This can lead to situations where we simply forego the check, because we're in a hurry or feel it is low risk.

The reason why an "eyeball comparison" is most often enough is that for an attacker it is really, really hard to create a file with a SHA-256 hash that is "almost the same" as for the original file. It's almost as hard as creating a SHA-256 hash that is the same as for the original file. You could probably assume that if they can create one, they can create the other.

The properties of SHA-256 (and indeed any cryptographic hash) is such that even the slightest change to the file results in a widely different hash value.

1
  • This is a very good point! – MEMark Jul 31 at 9:54
3

When you first calculate the sum of a file, it produces an output consisting of the sum, two spaces, and the name of the file that produced that sum. If you redirect that output to a file, you can later use the "-c" (for "check") option to automatically check every file listed, to see if the sum still matches.

So, create a text file called "checksum.txt" with one line:

d9cd63f187db2daea1371289508c63a7a24c46316f15ac61f030a7d6ea423915  downloaded.pkg

Then run the command:

shasum -a 256 -c checksum.txt

The command will calculate the sha-256 checksum of the file "downloaded.pkg", compare the result with the precomputed value, and tell you if it matched or not.

You might not even have to create the sum file yourself; most of the time, websites that provide checksums will let you download a text file that's already in the proper format.

1
  • This is a nice option. Of course, one has to then remove the checksum file that was created afterwards. For checking multiple files this approach becomes more attractive I think. I suppose it’s a matter of preference whether this is desirable or not. – TransferOrbit Apr 21 '20 at 9:30
2

You can compare the checksum directly with a bash function:

function checksha256() {
    # Usage: checksha256 file checksum
    if [[ $(shasum -a 256 "$1" | cut -f 1 -d' ') == "$2" ]]; then
        echo Match
    else
        echo No match
    fi
}

or

function checksha256() {
    # Usage: checksha256 file checksum
    echo "$1  $2" | shasum -s -a 256 -c
}

The two spaces are important in this case because that's the format shasum expects.

4
  • Thanks for this @nohillside. It’s nice to have a function if one wants to do this checksum comparison quite often. Where does one ‘store’ such a function? In one’s environment or as a script somehow? (For incidental use, it requires a bit more typing I suppose.) – TransferOrbit Apr 21 '20 at 9:15
  • 1
    @TransferOrbit In .bashrc usually – nohillside Apr 21 '20 at 9:21
  • On my macOS (Catalina 10.15.4), which runs zsh by default, the sha256sum command does not exist (used in your second alternative). Using shasum -a 256 -c does work, however. – TransferOrbit Apr 21 '20 at 9:52
  • @TransferOrbit Ah, typo, it's the same command in both cases – nohillside Apr 21 '20 at 10:00
1

One solution is to use diff to compare strings of the two hashes. Fortunately, this can be done in a single command-line entry as follows:

diff -is <(echo "d9cd63f187db2daea1371289508c63a7a24c46316f15ac61f030a7d6ea423915  /path/to/downloaded.pkg") <(shasum -a 256 /path/to/downloaded.pkg)

An important note: There must be two spaces between the hash in the first part of the term and the path to your downloaded file.

As an alternative, one can use shasum's built-in check option:

echo "d9cd63f187db2daea1371289508c63a7a24c46316f15ac61f030a7d6ea423915  /path/to/downloaded.pkg" | shasum -a 256 -c

Portions of this answer exist in various places, but despite avid searching I haven’t found that it’s been put together anywhere. If there are better alternatives, I’d be happy to hear of them.

0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .