1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
from typing import (
Union,
cast,
)
try:
from Cryptodome.Hash import (
keccak,
)
except ImportError:
try:
from Crypto.Hash import (
keccak,
)
except ImportError as exc:
raise ImportError(
"Could not import either 'Cryptodome' or 'Crypto' namespace. "
"Please install pycryptodome package.") from exc
from eth_hash.abc import (
BackendAPI,
PreImageAPI,
)
class CryptodomePreimage(PreImageAPI):
def __init__(self, prehash: bytes) -> None:
self._hash = keccak.new(data=prehash, digest_bits=256, update_after_digest=True)
# pycryptodome doesn't expose a `copy` mechanism for it's hash objects
# so we keep a record of all of the parts for when/if we need to copy
# them.
self._parts = [prehash]
def update(self, prehash: bytes) -> None:
self._hash.update(prehash)
self._parts.append(prehash)
def digest(self) -> bytes:
return cast(bytes, self._hash.digest())
def copy(self) -> "CryptodomePreimage":
return CryptodomePreimage(b"".join(self._parts))
class CryptodomeBackend(BackendAPI):
def keccak256(self, prehash: Union[bytearray, bytes]) -> bytes:
hasher = keccak.new(data=prehash, digest_bits=256)
return cast(bytes, hasher.digest())
def preimage(self, prehash: Union[bytearray, bytes]) -> PreImageAPI:
return CryptodomePreimage(prehash)
backend = CryptodomeBackend()
keccak256 = backend.keccak256
preimage = backend.preimage
|