Building a File Fingerprint in Python
Calculate a file fingerprint, save it as a reference, then change the file and compare the results.
For a browser-based option, use my free file fingerprint checker.
A hash turns data into a fixed-length value, often called a fingerprint. We'll use SHA-256, a hash method producing 32 bytes, small units of stored data. It displays them as 64 hexadecimal characters: digits 0 to 9 and letters a to f.
You'll need Python 3, a plain-text editor and a command window. No extra packages are required.
1. Create the example file
A text editor may add a line ending even when you only type abc. Let Python write the exact three bytes instead. Save this as MakeExample.py in your practice folder:
from pathlib import Path
Path("Example.txt").write_bytes(b"abc")
Run it from a command window in that folder:
python3 MakeExample.py
Use your installation's Python 3 command if it is not named python3. This creates or replaces Example.txt, so use a practice folder without a file you need to keep. b"abc" is a bytes value; write_bytes adds no line ending. The file now contains exactly three bytes, regardless of your editor's line-ending setting.
2. Save the program
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())
HashLib.sha256() starts the calculation. Each update adds the next block of bytes; adding blocks works like adding their combined contents at once. After the file ends, hexdigest returns the printable value.
The input opens in rb, read-only binary mode, without translating line endings. with closes it when reading finishes. Nothing is printed as a complete fingerprint until the full read succeeds.
Use known regular files, such as documents. Stat.S_ISREG checks the opened file's type, but a special file can block during opening before that check runs.
3. Calculate the fingerprint
Open a command window in your folder and run:
python3 FingerprintFile.py Example.txt
Use your installation's Python 3 command if it is not named python3. The output is:
SHA-256: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
Bytes read: 3
The exit code, a small result number another script can check, is 0 when calculation succeeds or 2 for an input/command error. This program calculates one value; it does not compare values or return a mismatch code.
4. Change the file and compare
Copy the example to another file and calculate its fingerprint. The values should match. Add a character to the copy and calculate again; its stored contents changed, so expect a different value.
Keep the reference separately from the checked file. If someone can replace both, they can calculate a new value and make the replacement match. A fingerprint from the same untrusted page as a download adds no independent reason to trust it.
The program passed 15 checks, including fixed expected values for empty input and abc, binary bytes, block boundaries, line endings and errors. Other successful cases were checked against a separate one-call calculation. Tested input bytes remained unchanged.
A match checks content against a reference, not the author's identity or whether the file is safe to open. Different files can share a fixed-length value. When both stable files are available and you need a direct byte-for-byte answer, compare their contents directly.
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 time limits.
Save output to a new report filename, not over the input. Do not use this calculation as a password-storage design; protecting passwords is a different job.
Reference
More free code guides
- Building a Time-Window Log Summary in Python
- Comparing Connection-Log Summaries in Python
- Comparing File Contents in Python
- Listing a Folder's Files in Python
- Comparing Folder File Lists in Python
- Checking a Saved File Fingerprint in Python
- Finding Repeated Log Entries in Python
- Finding Time Gaps in a Log with Python
- Counting Log Entries by Minute in Python