diff --git a/README.rst b/README.rst index 5fd9db1..02981de 100644 --- a/README.rst +++ b/README.rst @@ -52,12 +52,11 @@ The following are mandatory dependencies for this module: The following are optional dependencies for this module: -- `pysha3 `_, for the ``keccak`` hash functions. - `blake3 `_, for the ``blake3`` hash function. - `pyskein `_, for the ``skein`` hash functions. - `mmh3 `_, for the ``murmur3`` hash functions. - `pycryptodomex `_, for the ``ripemd-160`` hash function, \ - the ``kangarootwelve`` hash function and the ``sha2-512-224``/``sha2-512-256`` hash functions. + the ``kangarootwelve`` hash function, the ``keccak`` hash functions and the ``sha2-512-224``/``sha2-512-256`` hash functions. You can install the latest release together with all optional dependencies as follows: diff --git a/docs/getting-started.rst b/docs/getting-started.rst index bc55f50..902d9c1 100644 --- a/docs/getting-started.rst +++ b/docs/getting-started.rst @@ -38,12 +38,11 @@ The following are mandatory dependencies for this module: The following are optional dependencies for this module: -- `pysha3 `_, for the ``keccak`` hash functions. - `blake3 `_, for the ``blake3`` hash function. - `pyskein `_, for the ``skein`` hash functions. - `mmh3 `_, for the ``murmur3`` hash functions. - `pycryptodomex `_, for the ``ripemd-160`` hash function, \ - the ``kangarootwelve`` hash function and the ``sha2-512-224``/``sha2-512-256`` hash functions. + the ``kangarootwelve`` hash function, the ``keccak`` hash functions and the ``sha2-512-224``/``sha2-512-256`` hash functions. You can install the latest release together with all optional dependencies as follows: diff --git a/multiformats/multihash/_hashfuns/keccak.py b/multiformats/multihash/_hashfuns/keccak.py index 163fea1..e6149de 100644 --- a/multiformats/multihash/_hashfuns/keccak.py +++ b/multiformats/multihash/_hashfuns/keccak.py @@ -1,36 +1,29 @@ """ - Implementation for the ``keccak`` hash functions, using the optional dependency `pysha3 `_. + Implementation for the ``keccak`` hash functions, using the optional dependency `pycryptodomex `_. """ from __future__ import annotations -import hashlib from typing import Optional from multiformats.varint import BytesLike from .utils import Hashfun, validate_hashfun_args def _keccak(digest_bits: int) -> Hashfun: - # FIXME: pysha3 is not longer available - raise NotImplementedError("keccak hashes are not currently supported.") - # pylint: disable = unreachable try: - import sha3 # type: ignore # pylint: disable = import-outside-toplevel + from Cryptodome.Hash import keccak # pylint: disable = import-outside-toplevel except ImportError as e: - raise ImportError("Module 'sha3' must be installed to use 'keccak' hash functions. Consider running 'pip install pysha3'.") from e - h = getattr(sha3, f"keccak_{digest_bits}") + raise ImportError("Module 'pycryptodome' must be installed to use 'keccak' hash functions. Consider running 'pip install pycryptodome'.") from e + def hashfun(data: BytesLike, size: Optional[int] = None) -> bytes: validate_hashfun_args(data, size, digest_bits//8) - m: hashlib._Hash = h() # pylint: disable = no-member + m = keccak.new(digest_bits=digest_bits) m.update(data) d = m.digest() return d if size is None else d[:size] return hashfun def _jit_register_keccak(m, register) -> bool: # type: ignore - # FIXME: pysha3 is not longer available - raise NotImplementedError("keccak hashes are not currently supported.") - # pylint: disable = unreachable digest_bits = int(m[1]) if register is not None: register(f"keccak-{digest_bits}", _keccak(digest_bits), digest_bits//8) diff --git a/multiformats/multihash/raw.py b/multiformats/multihash/raw.py index 69c2f75..4f53110 100644 --- a/multiformats/multihash/raw.py +++ b/multiformats/multihash/raw.py @@ -4,12 +4,11 @@ Hash functions are implemented using the following modules: - `hashlib `_, for the ``sha``/``shake`` hash functions and the ``blake2`` hash functions. - - `pysha3 `_, for the ``keccak`` hash functions. - `blake3 `_, for the ``blake3`` hash function. - `pyskein `_, for the ``skein`` hash functions. - `mmh3 `_, for the ``murmur3`` hash functions. - `pycryptodomex `_, for the ``ripemd-160`` hash function, \ - the ``kangarootwelve`` hash function and the ``sha2-512-224``/``sha2-512-256`` hash functions. + the ``kangarootwelve`` hash function, the ``keccak`` hash functions and the ``sha2-512-224``/``sha2-512-256`` hash functions. All modules other than `hashlib `_ are optional dependencies. The :func:`get` function attempts to dynamically import any optional dependencies required by desired multihash @@ -276,7 +275,7 @@ def _jit_register_hashfun_dbl(name: str, check_only: bool = False) -> bool: _jit_register_hashfun_dir = { "sha": _jit_register_hashfun_sha, "bla": _jit_register_hashfun_bla, - # "kec": _jit_register_hashfun_kec, # kec is currently unavailable + "kec": _jit_register_hashfun_kec, "ske": _jit_register_hashfun_ske, "mur": _jit_register_hashfun_mur, "md5": _jit_register_hashfun_md5, diff --git a/setup.cfg b/setup.cfg index 3d6c6a0..29d5594 100644 --- a/setup.cfg +++ b/setup.cfg @@ -46,14 +46,12 @@ dev = pylint pytest pytest-cov - ; pysha3 blake3 pyskein mmh3 pycryptodomex rich # optional dependency of typing_validation full = - ; pysha3 blake3 pyskein mmh3 diff --git a/test/test_03_multihash.py b/test/test_03_multihash.py index 0bffc03..ba44c26 100644 --- a/test/test_03_multihash.py +++ b/test/test_03_multihash.py @@ -10,10 +10,8 @@ import pytest import skein # type: ignore from blake3 import blake3 # type: ignore -# import sha3 # type: ignore -# FIXME: find an alternative implementation for keccak import mmh3 # type: ignore -from Cryptodome.Hash import RIPEMD160, KangarooTwelve, SHA512 +from Cryptodome.Hash import RIPEMD160, KangarooTwelve, SHA512, keccak from multiformats import multihash from multiformats.multihash import wrap, digest, unwrap @@ -79,12 +77,11 @@ def skein_digest(data: bytes, variant: int, digest_bits: int, size: Optional[int d = m.digest() return d if size is None else d[:size] -# def keccak_digest(data: bytes, digest_bits: int, size: Optional[int]) -> bytes: -# m: hashlib._Hash = getattr(sha3, f"keccak_{digest_bits}")() -# m.update(data) -# d = m.digest() -# return d if size is None else d[:size] -# FIXME: find an alternative implementation for keccak +def keccak_digest(data: bytes, digest_bits: int, size: Optional[int]) -> bytes: + m: hashlib._Hash = keccak.new(digest_bits=digest_bits) + m.update(data) + d = m.digest() + return d if size is None else d[:size] # def murmur3_digest(data: bytes, variant: str, digest_bits: int, size: Optional[int]) -> bytes: # assert variant in ("32", "x64") @@ -218,13 +215,12 @@ def test_skein(data: bytes, version: int, size: Optional[int]) -> None: hash_fn = f"skein{version}-{digest_bits}" _test(hash_fn, data, skein_digest(data, version, digest_bits, size), size) -# @pytest.mark.parametrize("digest_bits", (224, 256, 384, 512)) -# @pytest.mark.parametrize("data", data_samples) -# @pytest.mark.parametrize("size", (None, 16, 28)) -# def test_keccak(data: bytes, digest_bits: int, size: Optional[int]) -> None: -# hash_fn = f"keccak-{digest_bits}" -# _test(hash_fn, data, keccak_digest(data, digest_bits, size), size) -# FIXME: find an alternative implementation for keccak +@pytest.mark.parametrize("digest_bits", (224, 256, 384, 512)) +@pytest.mark.parametrize("data", data_samples) +@pytest.mark.parametrize("size", (None, 16, 28)) +def test_keccak(data: bytes, digest_bits: int, size: Optional[int]) -> None: + hash_fn = f"keccak-{digest_bits}" + _test(hash_fn, data, keccak_digest(data, digest_bits, size), size) # @pytest.mark.parametrize("version", ("32", "x64")) # @pytest.mark.parametrize("data", data_samples) diff --git a/tox.ini b/tox.ini index fef5fc9..029e652 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,6 @@ deps = pylint pytest pytest-cov - ; pysha3 blake3 pyskein mmh3