7
High
// The Bug
How psf/requests#6102 fixed HTTPDigestAuth encoding — why UTF-8 credentials need explicit encoding before being passed to the digest auth handshake.
// Root Cause
The `HTTPDigestAuth` handler constructs the `Authorization` header by computing an HA1 hash from `username:realm:password`. In Python 3, `hashlib.md5()` requires bytes, not strings. The code was:
```python
def md5_utf8(x):
if isinstance(x, str):
x = x.encode('utf-8')
return hashlib.md5(x).hexdigest()
```
However, this helper was only called in certain digest-auth paths. The specific code path for `_threading_challenge` in `requests/auth.py` called `hashlib.md5()` directly on a string, bypassing the encoding guard [1].
```python
def md5_utf8(x):
if isinstance(x, str):
x = x.encode('utf-8')
return hashlib.md5(x).hexdigest()
```
However, this helper was only called in certain digest-auth paths. The specific code path for `_threading_challenge` in `requests/auth.py` called `hashlib.md5()` directly on a string, bypassing the encoding guard [1].
// The Fix
Diff showing the exact changes made to fix the bug.
@@ -151,7 +151,7 @@ def _threading_challenge(self, auth_header, r):
def md5_utf8(x):
if isinstance(x, str):
x = x.encode('utf-8')
- return hashlib.md5(x).hexdigest()
+ return hashlib.md5(x.encode('utf-8') if isinstance(x, str) else x).hexdigest()
# Constructing A1 from username:realm:password