Tidy Desk Digital ยท Free guides

Checking a Saved File Fingerprint in Python

This is part two of Building a File Fingerprint in Python. That program calculates SHA-256, a 64-character fingerprint of a file's bytes. Here we'll reuse its module and add a checker that returns a match, mismatch or error.

You'll need Python 3, the FingerprintFile.py module from part one, a plain-text editor and a command window. No extra packages are required.

1. Reuse the fingerprint module

Keep FingerprintFile.py from part one's program step in your practice folder. A module is a Python source file that another program can import. We'll call its FingerprintFile function rather than repeat the file-reading code here.

The module returns a fingerprint and byte count after the complete read succeeds. Its binary read leaves stored bytes and line endings unchanged. Use known regular files, such as documents; the module's type check happens after opening, so a special file can block before that check.

2. Create a known reference case

Save this as MakeExample.py beside the module:

from pathlib import Path


Path("Example.txt").write_bytes(b"abc")

Run:

python3 MakeExample.py

Use your installation's Python 3 command if it is not named python3. This creates or replaces Example.txt, so keep the exercise in a practice folder without a file you need to preserve. Python writes exactly the three bytes abc, with no line ending. Their expected SHA-256 value is:

ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad

A line ending would add bytes and change that value. This setup makes the first test independent of your editor's line-ending setting.

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 b"abc" to b"abd" in MakeExample.py, run that setup script again, then rerun the checker with the original reference. The output becomes:

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.

To try this comparison without a command window, choose your file and paste the saved reference into my file fingerprint checker. It runs on your device and accepts files up to 16 MiB.

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

More free code guides