diff --git a/wizard-work/spark/file_hash.py b/wizard-work/spark/file_hash.py new file mode 100644 index 0000000..aa97daa --- /dev/null +++ b/wizard-work/spark/file_hash.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +""" +File Hash Calculator - Computes cryptographic hashes for files. +Supports: sha256, sha1, sha512, md5, blake2b, blake2s, crc32 +""" +import argparse +import hashlib +import binascii +import sys +from pathlib import Path + + +def compute_hash(filepath: str, algorithm: str = "sha256", buffer_size: int = 65536) -> str: + """Compute hash of a file using specified algorithm.""" + algorithms = { + "sha256": hashlib.sha256, + "sha1": hashlib.sha1, + "sha512": hashlib.sha512, + "md5": hashlib.md5, + "blake2b": hashlib.blake2b, + "blake2s": hashlib.blake2s, + } + + if algorithm not in algorithms: + raise ValueError(f"Unknown algorithm: {algorithm}. Available: {list(algorithms.keys())}") + + hasher = algorithms[algorithm]() + + with open(filepath, "rb") as f: + while True: + data = f.read(buffer_size) + if not data: + break + hasher.update(data) + + return hasher.hexdigest() + + +def compute_crc32(filepath: str, buffer_size: int = 65536) -> str: + """Compute CRC32 checksum.""" + crc = 0 + with open(filepath, "rb") as f: + while True: + data = f.read(buffer_size) + if not data: + break + crc = binascii.crc32(data, crc) + return format(crc & 0xFFFFFFFF, '08x') + + +def main(): + parser = argparse.ArgumentParser(description="Compute file hashes") + parser.add_argument("file", help="File to hash") + parser.add_argument("-a", "--algorithm", default="sha256", + choices=["sha256", "sha1", "sha512", "md5", "blake2b", "blake2s", "crc32"], + help="Hash algorithm (default: sha256)") + parser.add_argument("-j", "--json", action="store_true", + help="Output as JSON") + + args = parser.parse_args() + + filepath = Path(args.file) + if not filepath.exists(): + print(f"Error: File not found: {filepath}", file=sys.stderr) + sys.exit(1) + + if args.algorithm == "crc32": + result = compute_crc32(str(filepath)) + else: + result = compute_hash(str(filepath), args.algorithm) + + if args.json: + import json + print(json.dumps({ + "file": str(filepath), + "algorithm": args.algorithm, + "hash": result, + "length": len(result) + })) + else: + print(f"{args.algorithm}:{result}") + + +if __name__ == "__main__": + main() \ No newline at end of file