All about checksums, including basic info. and usage
TLDR;
# 1. Check to see if file "filename" has this expected hash:
# `expected_checksum_hash`
echo "expected_checksum_hash filename" | sha256sum --check
# 2. Check to see if these two files ("path/to/file1" and "path/to/file2")
# have the same checksum hash
echo "$(sha256sum "path/to/file1" | gawk '{ print $1 }') path/to/file2" \
| sha256sum --check
# OR (same as #2 just above)
file1_hash="$(sha256sum "path/to/file1" | gawk '{ print $1 }')" \
&& echo "$file1_hash path/to/file2" | sha256sum --check
DETAILS:
1. Background info
Note: you can use sha256sum
or sha512sum
in any of the examples below. These are the recommended and most-robust cryptographic checksums, with sha512sum
, of course, being stronger.
There is also md5sum
, but it isn't as robust, but is still commonly used for data integrity checks. Whenever possible, I recommend you use sha256sum
or sha512sum
instead. Wikipedia states that md5sum
is still good for data integrity checks, but is "no longer deemed secure" and shouldn't be used for cryptographic purposes. So, just use sha256sum
or sha512sum
above, instead.
There are even more, however. Here is a list of the various checksum program you can technically use in any of the examples below:
sha1sum
sha224sum
sha256sum
sha384sum
sha512sum
shasum # general-purpose tool, requires specifying the algorithm
md5sum
2. Get the checksum of a file:
sha256sum path/to/any/file
Example:
$ sha256sum FoxitReader.enu.setup.2.4.4.0911.x64.run.tar.gz
6b579bd4ecdf86f7e70a009886c511da0b5085b831b0d6afc42442cabc249b90 FoxitReader.enu.setup.2.4.4.0911.x64.run.tar.gz
Notice that the output of the sha256sum
command is the numerical checksum hash followed by the file name this checksum corresponds to. You can store this checksum into a file named sha256sum.txt
like this:
sha256sum path/to/file > sha256sum.txt
3. Compare the checksum of a file against a previously-stored or already-known checksum:
Now, assuming you want to check the integrity of the file against this known checksum in that file, you can test the file again like this:
# This causes the program to re-do the checksum of the file specified inside
# sha256sum.txt, and then compare it to the checksum in that same file. If they
# (the re-calculated checksum and the previously-stored checksum) match, it will
# output the name of the file followed by "OK".
sha256sum --check sha256sum.txt
Example:
$ sha256sum --check sha256sum.txt
FoxitReader.enu.setup.2.4.4.0911.x64.run.tar.gz: OK
You can also manually pipe these things (the expected checksum hash and filename) to the checksum program, like this. This is really useful for when you need to check a downloaded file against a known checksum published online where you downloaded it. This way you can check for data integrity to ensure the downloaded file was downloaded successfully.
# 1. pipe to the checksum program directly
echo "expected_checksum_hash filename" | sha256sum --check
# 2. OR, manually create the checksum file, and *then* run it on that file
# as done above
echo "expected_checksum_hash filename" > sha256sum.txt
sha256sum --check sha256sum.txt # same as previously done above
Example of option 1 just above:
$ echo "6b579bd4ecdf86f7e70a009886c511da0b5085b831b0d6afc42442cabc249b90 \
> FoxitReader.enu.setup.2.4.4.0911.x64.run.tar.gz" | sha256sum --check
FoxitReader.enu.setup.2.4.4.0911.x64.run.tar.gz: OK
4. To compare the checksum of file1
to file2
:
Sometimes you have two downloaded files, or two copies of what you think are the same file, and you just want to ensure they are in fact the same (or different). Building on the information above, there are a few ways to do this.
Manually check the checksum of each file, manually looking at the hashes to ensure they match:
sha256sum 'path/to/file1'
sha256sum 'path/to/file2'
# now visually inspect both hashes
OR [RECOMMENDED] automatically test file1 against file2:
# Do some trickery to compare the hash of file1 agains the hash of file2.
# Effectively, what we have done is this:
# `echo "checksum_hash_from_file1 path/to/file2" | sha256sum --check`
# This therefore is checking to see if the hash from file1 matches the hash
# from file2.
echo "$(sha256sum "path/to/file1" | gawk '{ print $1 }') path/to/file2" \
| sha256sum --check
# OR (same as just above)
file1_hash="$(sha256sum "path/to/file1" | gawk '{ print $1 }')" \
&& echo "$file1_hash path/to/file2" | sha256sum --check
The way this works is that first it checks the checksum of file1, piping the output (hash and filename) to gawk
, which is the GNU version of awk
, which is a pattern-matching and text processing language. The gawk '{ print $1 }'
command simply says to strip the first space-separated text field (indicated by $1
), and retain it only. That's the checksum hash from file1. Then, we append the path/to/file2
and pipe this whole thing to be checked, as done previously above.
In effect, we are tricking the checksum program into thinking we have a previously-obtained hash from file2, and we'd like to check it against a newly-calculated hash from file2. Since we used the hash from file1, however, but the filename of file2, we know that if it passes it is really saying file1 and file2 have the same hash, and are therefore identical files.
Example:
# technique 1
$ echo "$(sha256sum "FoxitReader.enu.setup.2.4.4.0911.x64.run.tar.gz" \
| gawk '{ print $1 }') FoxitReader.enu.setup.2.4.4.0911_NEW.x64.run.tar.gz" \
| sha256sum --check
FoxitReader.enu.setup.2.4.4.0911_NEW.x64.run.tar.gz: OK
# technique 2
$ file1_hash="$(sha256sum "FoxitReader.enu.setup.2.4.4.0911.x64.run.tar.gz" \
| gawk '{ print $1 }')" \
&& echo "$file1_hash FoxitReader.enu.setup.2.4.4.0911_NEW.x64.run.tar.gz" \
| sha256sum --check
FoxitReader.enu.setup.2.4.4.0911_NEW.x64.run.tar.gz: OK