Compare any checksum with proposed checksum by website

I often download files from the Web and many websites suggest to compare a proposed checksum with what I obtain from my computer (usually in Terminal).

However, as the checksums tend to be quite long 64 characters for sha256 or 32 for md5 for example, I was wondering if a universal Terminal line could be created to use what a website might propose as a checksum?

I found askUbuntu question that is similar to mine, however restricted to md5sum. What I would like is a little bit what the contributor suggest but with any checksum algorithm (e.g., sha1, sha256, md5, etc.):

$ echo "checksum_suggested_by_site_to_be_put_here  filetohashA.txt" | md5 -c -

Any ideas?


Solution 1:

Here are two different approaches that can be taken, one using Automator and AppleScript, and the other using a bash script and Terminal.

Using Automator and AppleScript

The following example AppleScript code, used in an Automator Service1, set to Service receives selected files or folders in Finder, with a Run AppleScript action, will allow one to paste a copied MD5, SHA1, SHA256 or SHA512 checksum value into a dialog box and verify it against the selected file in Finder.

In macOS High Sierra, I saved the Automator Service1 as Verify Pasted Checksum. Then in Finder selecting a downloaded file for which I had a checksum copied to the clipboard, I right-clicked it and selected Verify Pasted Checksum from the Services context menu. I then pasted in the copied checksum and pressed the Enter key. It then returned the appropriate message.

  • 1 In macOS Mojave, and later, an Automator Service is called a Quick Action. There are also other minor nomenclature differences but they should be more obvious when comparing them to pre-macOS Mojave Automator workflows.

Example AppleScript code:

global pastedChecksum
global fileToCaculateChecksum

on run {input}

    set fileToCaculateChecksum to POSIX path of first item of input

    set pastedChecksum to text returned of (display dialog ¬
        "Paste checksum here:" buttons {"Cancel", "Verify Checksum"} default button ¬
        "Verify Checksum" default answer "" with title "Verify Checksum Matches Provided Value")

    set L to (length of pastedChecksum)

    if L = 32 then
        -- Validate MD5 checksum.
        set caculatedChecksum to do shell script "/sbin/md5 -q " & fileToCaculateChecksum's quoted form
        displayValidationMessage(caculatedChecksum)
    else if L = 40 then
        -- Validate SHA1 checksum.
        set caculatedChecksum to do shell script "/usr/bin/shasum " & fileToCaculateChecksum's quoted form & " | /usr/bin/awk '{print $1}'"
        displayValidationMessage(caculatedChecksum)
    else if L = 64 then
        -- Validate SHA256 checksum.
        set caculatedChecksum to do shell script "/usr/bin/shasum -a 256 " & fileToCaculateChecksum's quoted form & " | /usr/bin/awk '{print $1}'"
        displayValidationMessage(caculatedChecksum)
    else if L = 128 then
        -- Validate SHA512 checksum.
        set caculatedChecksum to do shell script "/usr/bin/shasum -a 512 " & fileToCaculateChecksum's quoted form & " | /usr/bin/awk '{print $1}'"
        displayValidationMessage(caculatedChecksum)
    else
        -- Unrecognized checksum.
        display dialog "The length of the pasted checksum was not recognized!" buttons {"OK"} ¬
            default button 1 with title "Unrecognized Checksum" with icon caution
    end if

end run

on displayValidationMessage(caculatedChecksum)
    if pastedChecksum is equal to caculatedChecksum then
        -- Checksum matched.
        display dialog "The checksum for '" & fileToCaculateChecksum & "' matched!" buttons {"OK"} ¬
            default button 1 with title "Valid Checksum"
    else
        -- Checksum did not match.
        display dialog "The checksum for '" & fileToCaculateChecksum & "' did not match!" buttons {"OK"} ¬
            default button 1 with title "Bad Checksum" with icon stop
    end if
end displayValidationMessage
  • Scroll to see additional code.

Note: The example AppleScript code is just that and does not contain any error handling as may be appropriate. The onus is upon the user to add any error handling as may be appropriate, needed or wanted. Have a look at the try statement and error statement in the AppleScript Language Guide. See also, Working with Errors.


Using bash and Terminal

If you want a bash solution for Terminal, use the following example bash code, saved to a file and made executable with chmod.

In Terminal:

touch vpc
open vpc

Copy and paste the example bash code, shown further below, into the opened document, then save and close it.

Back in Terminal:

chmod u+x vpc
./vpc

Note: I used vpc for: [V]erify [P]asted [C]hecksum

You can also place the, e.g., vpc executable in a directory that is within your PATH and be able to use it without ./ or its full qualified pathname.

Example bash code:

#!/bin/bash

if [[ $# -ne 2 ]]; then
    echo "  Missing argument!"
    echo "  Uasge: vpc pasted_checksum filename"
    echo "  Example: vpc 98d9402a8b446bdd57b4b6729b4d575e /path/to/filename"
    exit 1
fi

l=$(/usr/bin/awk -v var="$1" 'BEGIN {print length(var)}')
[ -f "$2" ] || l=0

case "$l" in
    32 )
                # Validate MD5 checksum.
            c="$(/sbin/md5 -q "$2")"
        ;;
    40 )
                # Validate SHA1 checksum.
            c="$(/usr/bin/shasum "$2" | /usr/bin/awk '{print $1}')"
        ;;
    64 )
                # ValidateSHA256 checksum.
            c="$(/usr/bin/shasum -a 256 "$2" | /usr/bin/awk '{print $1}')"
        ;;
    128 )
                # Validate SHA512checksum.
            c="$(/usr/bin/shasum -a 512 "$2" | /usr/bin/awk '{print $1}')"
        ;;
    0 )
            echo "  Bad Filename!"
            exit 1  
        ;;
    * )
            echo "  Unreconized Checksum!"
            exit 1
        ;;                                      
esac

    # Verify checksum matches provided value, using case insensitive matching.
shopt -s nocasematch
if [[ $1 == "$c" ]]; then
    echo "  The checksum for '""$2""' matched."
else
    echo "  The checksum for '""$2""' did not match!"
fi
shopt -u nocasematch
  • Scroll to see additional code.

Note: The example bash code contains some error handling. The onus is upon the user to add any additional error handling as may be appropriate, needed or wanted.