Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions Doc/library/hashlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ hash supplied more than 2047 bytes of data at once in its constructor or
.. index:: single: OpenSSL; (use in module hashlib)

Constructors for hash algorithms that are always present in this module are
:func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`, :func:`sha512`,
:func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`, :func:`sha3_512`,
:func:`shake_128`, :func:`shake_256`, :func:`blake2b`, and :func:`blake2s`.
:func:`md5` is normally available as well, though it may be missing or blocked
if you are using a rare "FIPS compliant" build of Python.
These correspond to :data:`algorithms_guaranteed`.
:func:`md5`, :func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`,
:func:`sha512`, :func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`,
:func:`sha3_512`, :func:`shake_128`, :func:`shake_256`, :func:`blake2b`, and
:func:`blake2s`. These correspond to :data:`algorithms_guaranteed`.

Any of these may nonetheless be missing or blocked in unusual environments,
such as a rare "FIPS compliant" build of Python or when OpenSSL's "FIPS mode"
is configured to exclude some algorithms from its default provider. Calling
the constructor of an algorithm that is unavailable raises :exc:`ValueError`.

Additional algorithms may also be available if your Python distribution's
:mod:`!hashlib` was linked against a build of OpenSSL that provides others.
Expand Down
12 changes: 5 additions & 7 deletions Lib/hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,16 +261,15 @@ def file_digest(fileobj, digest, /, *, _bufsize=2**18):
return digestobj


__logging = None
for __func_name in __always_supported:
# try them all, some may not work due to the OpenSSL
# version not supporting that algorithm.
try:
globals()[__func_name] = __get_hash(__func_name)
except ValueError as __exc:
import logging as __logging
__logging.error('hash algorithm %s will not be supported at runtime '
'[reason: %s]', __func_name, __exc)
except ValueError:
# Don't log here: logging at import time has global side effects and
# would tell the wrong audience; code that uses a missing algorithm
# gets a ValueError from the stub installed below.
# The following code can be simplified in Python 3.19
# once "string" is removed from the signature.
__code = f'''\
Expand All @@ -291,9 +290,8 @@ def {__func_name}(data=__UNSET, *, usedforsecurity=True, string=__UNSET):
'''
exec(__code, {"__UNSET": object()}, __locals := {})
globals()[__func_name] = __locals[__func_name]
del __exc, __code, __locals
del __code, __locals

# Cleanup locals()
del __always_supported, __func_name, __get_hash
del __py_new, __hash_new, __get_openssl_constructor
del __logging
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Importing :mod:`hashlib` no longer logs an error to stderr when a normally
guaranteed hash algorithm is unavailable in the current runtime (for example
under an OpenSSL FIPS configuration or a build using
:option:`--without-builtin-hashlib-hashes <--with-builtin-hashlib-hashes>`).
Code that actually uses the missing algorithm still gets a clear
:exc:`ValueError`.
Loading