AnP/Python/AnP/Models/HashModel.py

73 lines
2.0 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from hashlib import md5, sha1, sha256, blake2b
from zlib import crc32
from typing import Self, Protocol
from AnP.Utils.Checks import Check
class HashAlgorithm(Protocol):
def update(self:Self, data:bytes) -> None: ...
def hexdigest(self:Self) -> str: ...
class CRC32HashAlgorithm(HashAlgorithm):
def __init__(self:Self) -> None:
self.__value:int = 0
def update(self:Self, data:bytes) -> None:
self.__value = crc32(data, self.__value)
def hexdigest(self:Self) -> str:
return f"{self.__value & 0xFFFFFFFF:08x}"
class HashModel():
def __init__(self:Self, data:bytes = b"", chunk_size:int = 4096) -> None:
self.__chunk_size:int = chunk_size
self.md5:str = ""
self.sha1:str = ""
self.sha256:str = ""
self.blake2b:str = ""
self.crc32:str = ""
self.__hashes:list[HashAlgorithm] = ["md5", "sha1", "sha256", "blake2b", "crc32"]
self.__algorithms:list[HashAlgorithm] = [
method() for method in (md5, sha1, sha256, blake2b, CRC32HashAlgorithm)
]
len(data) and self.update(data)
def __update_chunk(self:Self, chunk:bytes) -> None:
for hash_algorithm in self.__algorithms:
hash_algorithm.update(chunk)
def update(self:Self, data:bytes|str, encode:str = "utf-8") -> None:
done:bool = False
if Check.is_string(data):
data = data.encode(encode)
if Check.is_binary(data):
while data:
chunk:bytes = data[:self.__chunk_size]
data = data[self.__chunk_size:]
self.__update_chunk(chunk)
done = True
if done:
name:str
for name in self.__hashes:
setattr(self, name, getattr(self.__algorithms[self.__hashes.index(name)], "hexdigest")())
return done
def compare(self:Self, other:Self) -> bool:
return all(getattr(self, name) == getattr(other, name) for name in self.__hashes)