hmac won't fall back if OpenSSL is available, the requested algorithm isn't in OpenSSL, but the algorithm is in hashlib.
If you [monkey]patch hashlib to include a new algorithm, you can't use that algorithm from hmac by name.
It appears that the OpenSSL implementation (known as _hashlib from inside hashlib, or _hashopenssl from inside hmac) doesn't actually return an UnsupportedDigestmodError, but rather it's base class ValueError.
MRE
# The following is MRE-specific to easily introduce a new name
# My use case involves a monkeypatch, but imagine any algorithm NOT implemented by OpenSSL, ONLY by hashlib
>>> hashlib.__builtin_constructor_cache['myhashalg'] = hashlib.md5
>>> hashlib.new('myhashalg', b'').digest().hex() # confirm hashlib can use that name
'd41d8cd98f00b204e9800998ecf8427e'
>>> hmac.digest(b'key', b'message', 'myhashalg')
Traceback (most recent call last):
File "<pyshell#nnn>", line 1, in <module>
hmac.digest(b'key', b'message', 'myhashalg')
File "C:\Python311\Lib\hmac.py", line 198, in digest
return _hashopenssl.hmac_digest(key, msg, digest)
ValueError: unsupported hash type myhashalg
The exception goes unhandled at
|
except _hashopenssl.UnsupportedDigestmodError: |
instead of falling through to let
hashlib handle it.
This also shows up in the stateful (non-oneshot) code at
|
except _hashopenssl.UnsupportedDigestmodError: |
Passing a callable works as intended with my monkeypatch, so I have a workaround. However, I'd argue that either
hmac is trying to catch the wrong thing, or OpenSSL is throwing the wrong thing, so some sort of fix is called for.
Environment
Windows 10 64-bit
Python 3.11.2
Possible fixes
Linked PRs
hmacwon't fall back if OpenSSL is available, the requested algorithm isn't in OpenSSL, but the algorithm is inhashlib.If you [monkey]patch
hashlibto include a new algorithm, you can't use that algorithm fromhmacby name.It appears that the OpenSSL implementation (known as
_hashlibfrom insidehashlib, or_hashopensslfrom insidehmac) doesn't actually return anUnsupportedDigestmodError, but rather it's base classValueError.MRE
# The following is MRE-specific to easily introduce a new name # My use case involves a monkeypatch, but imagine any algorithm NOT implemented by OpenSSL, ONLY by hashlib >>> hashlib.__builtin_constructor_cache['myhashalg'] = hashlib.md5 >>> hashlib.new('myhashalg', b'').digest().hex() # confirm hashlib can use that name 'd41d8cd98f00b204e9800998ecf8427e' >>> hmac.digest(b'key', b'message', 'myhashalg') Traceback (most recent call last): File "<pyshell#nnn>", line 1, in <module> hmac.digest(b'key', b'message', 'myhashalg') File "C:\Python311\Lib\hmac.py", line 198, in digest return _hashopenssl.hmac_digest(key, msg, digest) ValueError: unsupported hash type myhashalgThe exception goes unhandled at
cpython/Lib/hmac.py
Line 199 in 933dfd7
hashlibhandle it.This also shows up in the stateful (non-oneshot) code at
cpython/Lib/hmac.py
Line 61 in 933dfd7
Passing a callable works as intended with my monkeypatch, so I have a workaround. However, I'd argue that either
hmacis trying to catch the wrong thing, or OpenSSL is throwing the wrong thing, so some sort of fix is called for.Environment
Windows 10 64-bit
Python 3.11.2
Possible fixes
_hashopenssl.hmac_digestto correctly raise anUnsupportedDigestmodError(this looks like what was intended, given bpo-40645: use C implementation of HMAC #24920)ValueErrorinstead (asUnsupportedDigestmodErroris derived fromValueErrorthis would work, but may not be what is truly intended)Linked PRs