import hashlib
import sys

# trunc_by_hash.py
# This script is a tool to verify the hash of a file and truncate it based on the hash value. It accepts two command line arguments: a expected hash value and a file path. The expected hash value is used to identify the hash type and the file path is the path to the file that needs to be verified and truncated.
# The script supports the following hash types: md5, sha1, sha224, sha256, sha512, sha3_224, sha3_384, and sha3_512. If the length of the expected hash is not one of these, the script will return an error message.
# The script verifies the hash of the file by reading it byte by byte and updating the hash. It will exit as soon as the hash matches the expected hash. The length of the matching file is returned.
# If the hash verification is successful, the script will print out the matching file length and an example command line to truncate the file using the 'head' command in Linux.
#
# Usage: python trunc_by_hash.py <expected_hash> <file_path>
#
# Example: 
# python trunc_by_hash.py a0c1088973901485715076c131029c1c5d57998d783fe9fec4fd9920ad94f282 file.dat



def verify_file_hash(file_path, expected_hash):
    hash_functions = {
        32: hashlib.md5,
        40: hashlib.sha1,
        56: hashlib.sha224,
        64: hashlib.sha256,
        96: hashlib.sha512,
        128: hashlib.sha3_224,
        160: hashlib.sha3_384,
        256: hashlib.sha3_512,
    }
    hash_function = hash_functions.get(len(expected_hash))
    if hash_function is None:
        print('Error: Unsupported hash type')
        return None
    
    with open(file_path, 'rb') as f:
        hash = hash_function()
        print(f'Hash Type Identified: {hash.name}')
        byte = f.read(1)
        while byte:
            hash.update(byte)
            if hash.hexdigest() == expected_hash:
                return f.tell()
            byte = f.read(1)
        return None

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print('Usage: python trunc_by_hash.py <expected_hash> <file_path>')
        sys.exit(1)

    expected_hash = sys.argv[1].lower()
    file_path = sys.argv[2]
    matching_length = verify_file_hash(file_path, expected_hash)

    if matching_length is None:
        print('Hash verification failed.')
    else:
        print('Hash verification succeeded. Matching file length: {} bytes'.format(matching_length))
        print(f'Example tail command: head -c {matching_length} {file_path} > truncated_file')
