Check a file against a saved SHA-256 fingerprint. The program returns a match, mismatch or error so another script can tell the outcomes apart.

A fingerprint is a fixed-length value calculated from contents. SHA-256 is the hash method used here, displayed as 64 hexadecimal characters: digits 0 to 9 and letters a to f. We'll supply a known reference first, then change the file.

You'll need Python 3, a plain-text editor and a command window. No extra packages are required.

1. Create the example

Save Example.txt containing exactly abc, without a line ending. Its expected value is:

ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 

A line ending adds bytes, small units of stored data, so a file saved with one will not match this reference.

2. Add the fingerprint module

A module is a reusable Python source file. Save this as FingerprintFile.py:

import hashlib as HashLib import os as Os import stat as Stat import sys as Sys def FingerprintFile(FilePath): Fingerprint = HashLib.sha256() Total = 0 with open(FilePath, "rb") as InputFile: if not Stat.S_ISREG(Os.fstat(InputFile.fileno()).st_mode): raise ValueError("input must be a regular file") while True: Block = InputFile.read(65536) if not Block: break Fingerprint.update(Block) Total += len(Block) return Fingerprint.hexdigest(), Total def Main(): if len(Sys.argv) != 2: print("Usage: python3 FingerprintFile.py input-file", file=Sys.stderr) return 2 try: Fingerprint, Total = FingerprintFile(Sys.argv[1]) except (OSError, ValueError) as Problem: print(f"Fingerprint stopped: {Problem}", file=Sys.stderr) return 2 print(f"SHA-256: {Fingerprint}") print(f"Bytes read: {Total}") return 0 if __name__ == "__main__": Sys.exit(Main()) 

It reads in binary mode, leaving stored bytes and line endings unchanged, and adds blocks to the calculation. The value and byte count are returned after a complete read succeeds.

Use known regular files, such as documents. The type check runs after opening, and a special file can block before reaching that check.

3. Add the checker

Save CheckFingerprint.py beside the module:

import sys as Sys from FingerprintFile import FingerprintFile def CheckExpected(Value): if len(Value) != 64 or any(Character not in "0123456789abcdefABCDEF" for Character in Value): raise ValueError("expected fingerprint must be 64 hexadecimal characters") return Value.lower() def Main(): if len(Sys.argv) != 3: print("Usage: python3 CheckFingerprint.py input-file expected-sha256", file=Sys.stderr) return 2 try: Expected = CheckExpected(Sys.argv[2]) Actual, Total = FingerprintFile(Sys.argv[1]) except (OSError, ValueError) as Problem: print(f"Check stopped: {Problem}", file=Sys.stderr) return 2 if Actual == Expected: print(f"Fingerprint matches; bytes read: {Total}.") return 0 print("Fingerprint differs.") return 1 if __name__ == "__main__": Sys.exit(Main()) 

CheckExpected accepts exactly 64 hexadecimal characters, converting uppercase letters to lowercase. Spaces, a sha256: prefix and trailing line endings are rejected before opening the file. A correctly shaped but mistyped reference can still pass this check, so choose its source carefully.

Main calculates the current value and compares it with your reference. A failed read is an error, not a mismatch: the complete contents have not been checked.

4. Run a match

Open a command window in the folder and run:

python3 CheckFingerprint.py Example.txt ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad 

Use your installation's Python 3 command if it is not named python3. The output is:

Fingerprint matches; bytes read: 3. 

Change the file to abd, still without a line ending, and run the same command:

Fingerprint differs. 

The exit code, a small result number another script can check, is 0 for a match, 1 for a complete calculation that differs, and 2 for a command, reference-format or read error. Keep 1 and 2 separate: missing input or a bad reference does not establish changed content.

5. Use your own reference

Save the expected value separately from the file. If someone can replace both, they can calculate a new fingerprint and make their replacement match. A value from the same untrusted page as a download is not independent reason to trust it.

This checks contents against your reference, not the publisher's identity, malware or a digital signature, a separate method for checking who approved some data. Open or import the file in its intended application when usability matters.

The checker passed 20 checks, including invalid references, uppercase letters, read errors and a fixed abc reference that failed after changing the file to abd. The fingerprint module passed 15 separate checks.

Use a file that will not change during reading. The program does not lock it or take a frozen copy, and follows symbolic links, paths pointing to other files. Reading may affect recorded last-access times. Small read blocks do not impose file-size or runtime limits.

Different files can share a fixed-length fingerprint. When both stable files are available and you need a direct byte-for-byte answer, compare their contents. Save output under a new report filename, never over the input.

Reference