From 29c09af3024ef8ad9468586436064aba7fbccaf4 Mon Sep 17 00:00:00 2001 From: OneNobleSoul <75739931+OneNobleSoul@users.noreply.github.com> Date: Wed, 15 Jul 2026 06:04:19 +0200 Subject: [PATCH] fix hmac algorithm lookup for names without a hashlib attribute hashlib.algorithms_available includes a few names (ripemd160, sm3, sha512_224, md5-sha1) that config.py's validation already accepts but compute() rejected via getattr(hashlib, ...), since those don't exist as module attributes. pass the name straight to hmac.new instead. --- src/hookrelay/signature.py | 8 +++++--- tests/test_signature.py | 10 ++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/hookrelay/signature.py b/src/hookrelay/signature.py index 6a25b1e..1ebeeb7 100644 --- a/src/hookrelay/signature.py +++ b/src/hookrelay/signature.py @@ -5,10 +5,12 @@ def compute(secret: str, body: bytes, algorithm: str = "sha256") -> str: - algo = getattr(hashlib, algorithm, None) - if algo is None or algorithm not in hashlib.algorithms_available: + if algorithm not in hashlib.algorithms_available: raise ValueError(f"unsupported algorithm: {algorithm}") - return hmac.new(secret.encode("utf-8"), body, algo).hexdigest() + # pass the name straight to hmac/hashlib.new instead of getattr(hashlib, ...): + # some entries in algorithms_available (ripemd160, sm3, sha512_224, md5-sha1) + # have no matching hashlib module attribute and would falsely raise here. + return hmac.new(secret.encode("utf-8"), body, algorithm).hexdigest() def verify( diff --git a/tests/test_signature.py b/tests/test_signature.py index e25aca1..8987695 100644 --- a/tests/test_signature.py +++ b/tests/test_signature.py @@ -45,3 +45,13 @@ def test_verify_empty_provided(): def test_unsupported_algorithm(): with pytest.raises(ValueError): compute("secret", b"x", algorithm="rot13") + + +def test_compute_algorithm_without_hashlib_attribute(): + # ripemd160 is in hashlib.algorithms_available on most builds but has no + # hashlib.ripemd160 attribute, so getattr(hashlib, ...) would wrongly + # reject it even though it's a valid, config-approved algorithm. + if "ripemd160" not in hashlib.algorithms_available: + pytest.skip("ripemd160 not available on this build") + expected = hmac.new(b"secret", b"x", "ripemd160").hexdigest() + assert compute("secret", b"x", algorithm="ripemd160") == expected