DedSec Project

Calculate a file SHA-256 — DedSec Project

Recipe: streaming SHA-256 for local file verification Intended use and acceptance criteria This recipe calculates a SHA-256 digest of any local file without reading it into RAM at once. Use…

Recipe: streaming SHA-256 for local file verification

Intended use and acceptance criteria

This recipe calculates a SHA-256 digest of any local file without reading it into RAM at once. Use it to compare a previously trusted expected digest against a downloaded offline resource. The example exercises one-byte and 64 KiB read sizes and proves that adding one byte changes the result.

Complete runnable example

Save this as 02_File_hash.py and execute with Python 3. The fixture is disposable and has no network dependency.

import hashlib, tempfile
from pathlib import Path
def sha256_file(path, chunk_size=65536):
    if type(chunk_size) is not int or chunk_size < 1:
        raise ValueError("invalid chunk size")
    digest = hashlib.sha256()
    with open(path, "rb") as stream:
        for chunk in iter(lambda: stream.read(chunk_size), b""):
            digest.update(chunk)
    return digest.hexdigest()
with tempfile.TemporaryDirectory() as directory:
    item = Path(directory) / "αρχείο.bin"
    item.write_bytes(b"abc")
    expected = hashlib.sha256(b"abc").hexdigest()
    assert sha256_file(item, 1) == expected
    assert sha256_file(item, 65536) == expected
    item.write_bytes(b"abcd")
    assert sha256_file(item) != expected
    item.write_bytes(b"")
    assert sha256_file(item) == hashlib.sha256(b"").hexdigest()
print("PASS streaming file SHA-256")

Guarantees and limitations

The digest updates incrementally over raw bytes; hash results are independent of chunk size. Unicode characters in the path do not change the bytes being hashed. An empty file also has a valid deterministic digest. A SHA-256 match demonstrates identity to the trusted reference at comparison time, not publisher authenticity or immunity to concurrent edits. Hashing a file while another process is writing it may produce a digest of an inconsistent snapshot.

Adaptation lab

Run it against synthetic 10 MiB data using chunk sizes 1, 4096 and 65536 and compare digests. Catch FileNotFoundError separately from PermissionError. Decide whether to inspect file size and timestamp before and after hashing; neither alone is an atomic snapshot. Never replace signature verification with a self-published checksum.

Troubleshooting and release check

If two files with apparently identical text hash differently, compare encoded bytes, line endings, BOM and Unicode normalization. Do not decode or normalize when the goal is exact file integrity. If the expected digest came from the same untrusted download channel, investigate provenance before trusting it.