58 lines
1.5 KiB
Python
58 lines
1.5 KiB
Python
import base64
|
|
import dataclasses
|
|
import hashlib
|
|
from typing import IO, Union
|
|
|
|
HASH_CHUNK_SIZE = 4096
|
|
|
|
|
|
def _update(hashers, data: Union[bytes, IO[bytes]]):
|
|
if isinstance(data, bytes):
|
|
for hasher in hashers:
|
|
hasher.update(data)
|
|
else:
|
|
pos = data.tell()
|
|
while 1:
|
|
chunk = data.read(HASH_CHUNK_SIZE)
|
|
if not isinstance(chunk, bytes):
|
|
raise ValueError(f"Only accepts bytes or byte buffer objects, not {type(chunk)} buffers")
|
|
if not chunk:
|
|
break
|
|
for hasher in hashers:
|
|
hasher.update(chunk)
|
|
data.seek(pos)
|
|
|
|
|
|
def get_sha256_hex(data: Union[bytes, IO[bytes]]) -> str:
|
|
hasher = hashlib.sha256()
|
|
_update([hasher], data)
|
|
return hasher.hexdigest()
|
|
|
|
|
|
def get_sha256_base64(data: Union[bytes, IO[bytes]]) -> str:
|
|
hasher = hashlib.sha256()
|
|
_update([hasher], data)
|
|
return base64.b64encode(hasher.digest()).decode("ascii")
|
|
|
|
|
|
def get_md5_base64(data: Union[bytes, IO[bytes]]) -> str:
|
|
hasher = hashlib.md5()
|
|
_update([hasher], data)
|
|
return base64.b64encode(hasher.digest()).decode("utf-8")
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class UploadHashes:
|
|
md5_base64: str
|
|
sha256_base64: str
|
|
|
|
|
|
def get_upload_hashes(data: Union[bytes, IO[bytes]]) -> UploadHashes:
|
|
md5 = hashlib.md5()
|
|
sha256 = hashlib.sha256()
|
|
_update([md5, sha256], data)
|
|
return UploadHashes(
|
|
md5_base64=base64.b64encode(md5.digest()).decode("ascii"),
|
|
sha256_base64=base64.b64encode(sha256.digest()).decode("ascii"),
|
|
)
|