3

Suppose I try to verify the checksum of a file using:

echo '760382d5e8cdc5d0d079e8f754bce1136fbe1473be24bb885669b0e38fc56aa3 emacs-26.1.tar.gz' | \ sha256sum --check 

If the file is corrupt and the checksum is wrong, sha256sum will show this message:

emacs-26.1.tar.gz: FAILED sha256sum: WARNING: 1 computed checksum did NOT match 

I would like to know the actual checksum of the file (i.e. incorrect checksum that caused this error message). What are my options? If possible, I do not want to compute the checksum twice (once to see the "FAILED" message, and a second time to see the incorrect checksum).

(OS: Ubuntu 20.04)

2
  • 1
    I'm curious: what's the use for it? Commented Mar 27, 2021 at 7:48
  • @muru Sometimes, I download large files over an unreliable connection. I ask my neighbor to download the same file and I can determine whether or not the corruption is exactly the same as mine. Yes, I understand that I can calculate the checksum again, but checksums can take quite some time to compute on small/old computers. Commented Mar 27, 2021 at 9:05

3 Answers 3

2

Looking at the source code of the GNU coreutils implementation, the perl one (shasum) or the ast-open one (sum), none of them can be told to output the computed sum in verify mode.

With the perl one, it's easy to modify it though:

--- shasum.orig 2021-03-27 08:01:06.927965948 +0000 +++ shasum 2021-03-27 08:02:33.336241906 +0000 @@ -295,7 +295,7 @@ $isOK = 1; $num_OK++; } - else { $rsp .= "FAILED\n"; $err = 1; $match_errs++ } + else { $rsp .= "FAILED (expected $sum, got $digest)\n"; $err = 1; $match_errs++ } print $rsp unless ($status || ($quiet && $isOK)); } close(FH); 

And then:

$ echo '760382d5e8cdc5d0d079e8f754bce1136fbe1473be24bb885669b0e38fc56aa3 a' | ./shasum -a 256 -c a: FAILED (expected 760382d5e8cdc5d0d079e8f754bce1136fbe1473be24bb885669b0e38fc56aa3, got 3a1edb0672af06bc4712da1fcc00a09326e550d3f503ca41bf59d259f46afdc9) 
1

The shell script below solves the problem by saving the computed checksum into a variable. The saved checksum is then compared against the expected checksum. The saved checksum can then be displayed in an error message if needed.

#!/bin/sh file='emacs-26.1.tar.gz' expected='760382d5e8cdc5d0d079e8f754bce1136fbe1473be24bb885669b0e38fc56aa3' actual="$(sha256sum "$file" | awk '{print $1}')" if [ "$actual" = "$expected" ]; then echo "${file}: OK" else echo "${file}: FAILED" echo "Expected: $expected" >&2 echo "Observed: $actual" >&2 exit 1 fi 

The echo "${file}: OK mimics the output format of sha256sum --check, and the Expected: ... and Observed: ... is used in place of sha256sum --check's sha256sum: WARNING: 1 computed checksum did NOT match error message.

0

Maybe a bash function like this would work?

function check { file="$1" expected="$2" echo "$expected $file" | sha256sum --check result=$? if [ $result -ne 0 ]; then printf "Expected: %s\n" "$expected" printf "Observed: %s\n" $(sha256sum "$file" | awk '{print $1}') fi } 

Here's a demonstration:

#!/bin/bash function check { ... } file="emacs-26.1.tar.gz" expected=760382d5e8cdc5d0d079e8f754bce1136fbe1473be24bb885669b0e38fc56aa3 if [ ! -e "$file" ]; then touch "$file" fi echo "This is what a mismatched file looks like" check $file $expected printf "\n--------------------------------------\n" echo "This is what a matching file looks like" expected=$(sha256sum "$file" | awk '{print $1}') check $file $expected 

Output:

This is what a mismatched file looks like emacs-26.1.tar.gz: FAILED sha256sum: WARNING: 1 computed checksum did NOT match Expected: 760382d5e8cdc5d0d079e8f754bce1136fbe1473be24bb885669b0e38fc56aa3 Observed: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -------------------------------------- This is what a matching file looks like emacs-26.1.tar.gz: OK 
6
  • You're right. Tried with [ "$result" ] and result="$?" but got the same problem. -ne seems to handle it fine. After years of this, the quoting rules still drive me crazy. Commented Mar 27, 2021 at 8:21
  • If you make more sense to use if ! echo ... | sha256sum here. You have a few more missing quotes (around $result and around $(...)). Should be sha256sum -- "$file". Commented Mar 27, 2021 at 8:30
  • With the GNU implementation of sha256sum at least, you need two spaces between sum and file or it won't work properly for filenames that start with space characters. Commented Mar 27, 2021 at 8:33
  • backslashes and newlines in filenames need to be handled specially as well (replaced with \\ and \n respectively and lines prepended with backslash) Commented Mar 27, 2021 at 8:35
  • echo (at least some echo implementations, and in the case of bash that depends on whether the xpg_echo was enabled at compile time or runtime) will also mangle strings with backslashes. Best is use printf to output arbitrary data. Commented Mar 27, 2021 at 8:37

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.