import hashlib
import typing as tp
if tp.TYPE_CHECKING:
from hashlib import _Hash # pylint: disable = W0611 #pragma: no cover
from hashlib import _VarLenHash # pylint: disable = W0611 #pragma: no cover
class InterfaceHashlib:
__slots__ = (
'_to_bytes',
'_include_name',
'_include_class',
'_encoding',
)
INTERFACE = (
'to_bytes',
'md5',
'sha256',
'sha512',
'sha3_256',
'sha3_512',
'shake_128',
'shake_256',
'blake2b',
'blake2s',
)
def __init__(self,
to_bytes: tp.Callable[[bool, bool, str], bytes],
*,
include_name: bool,
include_class: bool,
encoding: str,
) -> None:
'''Interfacefor deriving cryptographic hashes from this container, pre-loaded with byte signatures from the calling container.
Args:
include_name: Whether container name is included in the bytes signature.
include_class: Whether class name is included in the byte signature.
encoding: Encoding to use for converting strings to bytes.
'''
self._to_bytes = to_bytes
self._include_name = include_name
self._include_class = include_class
self._encoding = encoding
def __call__(self,
include_name: tp.Optional[bool] = None,
include_class: tp.Optional[bool] = None,
encoding: tp.Optional[str] = None,
) -> 'InterfaceHashlib':
'''Interfacefor deriving cryptographic hashes from this container, pre-loaded with byte signatures from the calling container.
Args:
include_name: Whether container name is included in the bytes signature.
include_class: Whether class name is included in the byte signature.
encoding: Encoding to use for converting strings to bytes.
'''
return self.__class__(
to_bytes=self._to_bytes,
include_name=include_name if include_name is not None else self._include_name,
include_class=include_class if include_class is not None else self._include_class,
encoding=encoding if encoding is not None else self._encoding,
)
[docs] def to_bytes(self) -> bytes:
'''Return the byte signature for this container, suitable for passing to a cryptographic hash function.
'''
return self._to_bytes( # type: ignore # (need Protocol with __call__)
include_name=self._include_name,
include_class=self._include_class,
encoding=self._encoding,
)
[docs] def md5(self) -> '_Hash':
return hashlib.md5(self.to_bytes())
[docs] def sha256(self) -> '_Hash':
return hashlib.sha256(self.to_bytes())
[docs] def sha512(self) -> '_Hash':
return hashlib.sha512(self.to_bytes())
[docs] def sha3_256(self) -> '_Hash':
return hashlib.sha3_256(self.to_bytes())
[docs] def sha3_512(self) -> '_Hash':
return hashlib.sha3_512(self.to_bytes())
[docs] def shake_128(self) -> '_VarLenHash':
return hashlib.shake_128(self.to_bytes())
[docs] def shake_256(self) -> '_VarLenHash':
return hashlib.shake_256(self.to_bytes())
[docs] def blake2b(self, *,
digest_size: int = 64,
key: bytes = b'',
salt: bytes = b'',
person: bytes = b'',
fanout: int = 1,
depth: int = 1,
leaf_size: int = 0,
node_offset: int = 0,
node_depth: int = 0,
inner_size: int = 0,
last_node: bool = False,
# usedforsecurity: bool = True, # py 3.9
) -> '_Hash':
return hashlib.blake2b(
self.to_bytes(),
digest_size=digest_size,
key=key,
salt=salt,
person=person,
fanout=fanout,
depth=depth,
leaf_size=leaf_size,
node_offset=node_offset,
node_depth=node_depth,
inner_size=inner_size,
last_node=last_node,
# usedforsecurity=usedforsecurity,
)
[docs] def blake2s(self, *,
digest_size: int = 32,
key: bytes = b'',
salt: bytes = b'',
person: bytes = b'',
fanout: int = 1,
depth: int = 1,
leaf_size: int = 0,
node_offset: int = 0,
node_depth: int = 0,
inner_size: int = 0,
last_node: bool = False,
# usedforsecurity: bool = True,
) -> '_Hash':
return hashlib.blake2s(
self.to_bytes(),
digest_size=digest_size,
key=key,
salt=salt,
person=person,
fanout=fanout,
depth=depth,
leaf_size=leaf_size,
node_offset=node_offset,
node_depth=node_depth,
inner_size=inner_size,
last_node=last_node,
# usedforsecurity=usedforsecurity,
)