# compatibile Windows 11 # compatibile Ubuntu 24.10 # compatibile python 3.12.7 import hashlib import argparse import os def hash_file_blake2s(filename: str, digest_size: int = 32) -> str: """Calcola l'hash BLAKE2s di un file.""" if not 1 <= digest_size <= 32: raise ValueError("La dimensione del digest di BLAKE2s deve essere tra 1 e 32 byte.") try: with open(filename, "rb") as f: blake2s_hash = hashlib.blake2s(digest_size=digest_size) while True: chunk = f.read(4096) # Leggi in blocchi if not chunk: break blake2s_hash.update(chunk) return blake2s_hash.hexdigest() except FileNotFoundError: raise FileNotFoundError(f"File '{filename}' non trovato.") except Exception as e: raise Exception(f"Errore durante l'hashing: {e}") def hash_string_blake2s(text: str, digest_size: int = 32) -> str: """Calcola l'hash BLAKE2s di una stringa (UTF-8).""" if not 1 <= digest_size <= 32: raise ValueError("La dimensione del digest di BLAKE2s deve essere tra 1 e 32 byte.") return hashlib.blake2s(text.encode('utf-8'), digest_size=digest_size).hexdigest() def compare_hashes(hash1: str, hash2: str) -> bool: """Confronta due hash (case-insensitive).""" return hash1.lower() == hash2.lower() def main(): parser = argparse.ArgumentParser( description="Calcola o verifica l'hash BLAKE2s di file o stringhe.", formatter_class=argparse.RawTextHelpFormatter ) group = parser.add_mutually_exclusive_group(required=True) group.add_argument("-f", "--file", help="Calcola l'hash BLAKE2s di un file.") group.add_argument("-s", "--string", help="Calcola l'hash BLAKE2s di una stringa.") group.add_argument("-c", "--compare", nargs=2, metavar=('HASH1', 'HASH2'), help="Confronta due hash BLAKE2s (case-insensitive).") group.add_argument("-fv", "--file_verify", nargs=2, metavar=('FILE', 'HASH'), help="Verifica che il file FILE abbia l'hash HASH.") group.add_argument("-sv", "--string_verify", nargs=2, metavar=('STRING', 'HASH'), help="Verifica che la stringa STRING abbia l'hash HASH.") parser.add_argument("-d", "--digest_size", type=int, default=32, help="Dimensione del digest in byte (1-32, default: 32).") try: args = parser.parse_args() if args.file: file_hash = hash_file_blake2s(args.file, args.digest_size) print(f"BLAKE2s('{args.file}', digest_size={args.digest_size}) = {file_hash}") elif args.string: string_hash = hash_string_blake2s(args.string, args.digest_size) print(f"BLAKE2s(\"{args.string}\", digest_size={args.digest_size}) = {string_hash}") elif args.compare: hash1, hash2 = args.compare if compare_hashes(hash1, hash2): print(f"Gli hash corrispondono:\n{hash1}\n{hash2}") else: print(f"Gli hash NON corrispondono:\n{hash1}\n{hash2}") elif args.file_verify: filename, expected_hash = args.file_verify calculated_hash = hash_file_blake2s(filename, args.digest_size) if compare_hashes(calculated_hash, expected_hash): print(f"[PASS] L'hash del file {filename} corrisponde.") else: print(f"[FAIL] L'hash del file {filename} NON corrisponde.") print(f"Hash calcolato : {calculated_hash}") print(f"Hash atteso : {expected_hash}") elif args.string_verify: text, expected_hash = args.string_verify calculated_hash = hash_string_blake2s(text, args.digest_size) if compare_hashes(calculated_hash, expected_hash): print(f'[PASS] L\'hash della stringa "{text}" corrisponde.') else: print(f'[FAIL] L\'hash della stringa "{text}" NON corrisponde.') print(f"Hash calcolato : {calculated_hash}") print(f"Hash atteso : {expected_hash}") except SystemExit as e: # Cattura SystemExit e recupera il codice di uscita #sys.exit(e.code) # argpase help oppure non ci sono parametri pass except FileNotFoundError as e: print(f"Errore: {e}") #sys.exit(1) # Uscita con codice di errore != 0 pass except Exception as e: print(f"Errore inatteso: {e}") #sys.exit(1) pass if __name__ == "__main__": main()