85 lines
2.6 KiB
Python
85 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import hashlib
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
DEFAULT_BLOCK_SIZE = 1024 * 1024 # 1 MB
|
|
SUPPORTED_ALGOS = ["md5", "sha1", "sha224", "sha256"]
|
|
|
|
def compute_hash(path: Path, algorithm: str, block_size: int = DEFAULT_BLOCK_SIZE) -> str:
|
|
"""Compute the hash of a file using the chosen algorithm."""
|
|
try:
|
|
h = hashlib.new(algorithm)
|
|
except ValueError:
|
|
raise SystemExit(f"Error: Unsupported hash algorithm '{algorithm}'")
|
|
|
|
with path.open("rb") as f:
|
|
for chunk in iter(lambda: f.read(block_size), b""):
|
|
h.update(chunk)
|
|
|
|
return h.hexdigest()
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Compute hash(es) of a file or verify against a known hash."
|
|
)
|
|
parser.add_argument("file", type=Path, help="Path to the file to hash")
|
|
parser.add_argument(
|
|
"known_hash",
|
|
nargs="?",
|
|
help="Optional known hash to verify the file against",
|
|
)
|
|
|
|
parser.add_argument("-md5", action="store_true", help="Use MD5 algorithm")
|
|
parser.add_argument("-sha1", action="store_true", help="Use SHA-1 algorithm")
|
|
parser.add_argument("-sha224", action="store_true", help="Use SHA-224 algorithm")
|
|
parser.add_argument("-sha256", action="store_true", help="Use SHA-256 algorithm")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if not args.file.exists() or not args.file.is_file():
|
|
print(f"Error: File not found -> {args.file}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
selected_algos = [
|
|
algo
|
|
for algo, used in {
|
|
"md5": args.md5,
|
|
"sha1": args.sha1,
|
|
"sha224": args.sha224,
|
|
"sha256": args.sha256,
|
|
}.items()
|
|
if used
|
|
]
|
|
|
|
if not selected_algos:
|
|
selected_algos = ["sha1"] if args.known_hash else SUPPORTED_ALGOS
|
|
|
|
print()
|
|
if args.known_hash:
|
|
# Verification mode
|
|
algo = selected_algos[0]
|
|
digest = compute_hash(args.file, algo)
|
|
print(f"{algo.upper()} hash: {digest}")
|
|
if digest.lower() == args.known_hash.lower():
|
|
print("\033[32mCorrect\033[0m")
|
|
print("")
|
|
sys.exit(0)
|
|
else:
|
|
print("\033[31mIncorrect\033[0m")
|
|
print("")
|
|
sys.exit(1)
|
|
else:
|
|
# Normal hashing mode
|
|
print("Algorithm Hash")
|
|
print("--------- ----")
|
|
for algo in selected_algos:
|
|
digest = compute_hash(args.file, algo)
|
|
print(f"{algo.upper():<8} {digest}")
|
|
print()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|