1import hashlib
2
3# Compat wrapper to always include the `usedforsecurity=...` parameter,
4# which is only added from Python 3.9 onwards.
5# We use this flag to indicate that we use `md5` hashes only for non-security
6# cases (our ETag checksums).
7# If we don't indicate that we're using MD5 for non-security related reasons,
8# then attempting to use this function will raise an error when used
9# environments which enable a strict "FIPs mode".
10#
11# See issue: https://github.com/encode/starlette/issues/1365
12try:
13 # check if the Python version supports the parameter
14 # using usedforsecurity=False to avoid an exception on FIPS systems
15 # that reject usedforsecurity=True
16 hashlib.md5(b"data", usedforsecurity=False) # type: ignore[call-arg]
17
18 def md5_hexdigest(data: bytes, *, usedforsecurity: bool = True) -> str: # pragma: no cover
19 return hashlib.md5( # type: ignore[call-arg]
20 data, usedforsecurity=usedforsecurity
21 ).hexdigest()
22
23except TypeError: # pragma: no cover
24
25 def md5_hexdigest(data: bytes, *, usedforsecurity: bool = True) -> str:
26 return hashlib.md5(data).hexdigest()