49 lines
1.3 KiB
Python
49 lines
1.3 KiB
Python
"""Checksum Utilities
|
|
|
|
Small convenience functions to work with checksums.
|
|
"""
|
|
import hashlib
|
|
import os
|
|
|
|
from .types import PathLike
|
|
|
|
# How many bytes to read in one go. Taken from coreutils/gnulib
|
|
BLOCKSIZE = 32768
|
|
|
|
|
|
def hexdigest_file(path: PathLike, algorithm: str) -> str:
|
|
"""Return the hexdigest of the file at `path` using `algorithm`
|
|
|
|
Will stream the contents of file to the hash `algorithm` and
|
|
return the hexdigest. If the specified `algorithm` is not
|
|
supported a `ValueError` will be raised.
|
|
"""
|
|
hasher = hashlib.new(algorithm)
|
|
|
|
with open(path, "rb") as f:
|
|
|
|
os.posix_fadvise(f.fileno(), 0, 0, os.POSIX_FADV_SEQUENTIAL)
|
|
|
|
while True:
|
|
data = f.read(BLOCKSIZE)
|
|
if not data:
|
|
break
|
|
|
|
hasher.update(data)
|
|
|
|
return hasher.hexdigest()
|
|
|
|
|
|
def verify_file(path: PathLike, checksum: str) -> bool:
|
|
"""Hash the file and return if the specified `checksum` matches
|
|
|
|
Uses `hexdigest_file` to hash the contents of the file at
|
|
`path` and return if the hexdigest matches the one specified
|
|
in `checksum`, where `checksum` consist of the algorithm used
|
|
and the digest joined via `:`, e.g. `sha256:abcd...`.
|
|
"""
|
|
algorithm, want = checksum.split(":", 1)
|
|
|
|
have = hexdigest_file(path, algorithm)
|
|
|
|
return have == want
|