5

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?

9
  • You can use similar commands for other types of checksums. Not sure what exactly you are looking for here?
    – nohillside
    Commented Dec 13, 2019 at 10:57
  • @nohillside: I would like a command (similar to the one displayed in the question) that allows the use of any checksum algorithm that tells me whether the checksum matches or not. Something like this: step 1. have the generic command stored somewhere in the computer (e.g., Notes), 2. paste the checksum provided by the website at the appropriate place, 3. change the checksum command to the one requested by the website, 4. press enter, 5. Terminal tells me whether the the checksums (the one pasted and the one generated) match (or not). (shall I add this in my question?)
    – pdeli
    Commented Dec 13, 2019 at 14:09
  • So basically you want a script which automatically determines the type of the checksum and then calls the correct command to verify it? Can you add the list of all checksum types you want to cover, ideally with samples (or a download link to a sample)?
    – nohillside
    Commented Dec 13, 2019 at 14:23
  • macOS does not have the md5sum utility, but it has md5 and shasum that you can use. In Terminal, man md5 and man shasum to see what these utilities offer. You can also use openssl, e.g. openssl sha1 file -- See: openssl man page Commented Dec 13, 2019 at 14:39
  • @nohillside: not really automatically as there would be some copy/paste in the process. Say the website Y mentions that if one downloads file.txt the shasum checksum is 1a2b3c. What I would like is something as follows: compare 1a2b3c with shasum -a file.txt → if match then echo "ok", else echo "KO". And you would like to be able to swap shasum with md5, etc.
    – pdeli
    Commented Dec 13, 2019 at 15:08

1 Answer 1

4

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.

1
  • @pdeli, I don't know when you last saw my answer, but wanted to let you know I added a bash solution too. If you found either method I've presented useful, please consider an up-vote and or marking it as accepted, thanks. Commented Dec 16, 2019 at 18:10

You must log in to answer this question.

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