#31375: make_password shouldn't accept values other than bytes or string as an
argument
------------------------------+--------------------------------------
Reporter: iamdavidcz | Owner: nobody
Type: Bug | Status: new
Component: contrib.auth | Version: 3.0
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+--------------------------------------
Comment (by iamdavidcz):
[comment:2 Simon Charette], thank you for your testing. Could you tell me
what is your `PASSWORD_HASHERS` setting? I've tried to reproduce your
example on master using `PBKDF2PasswordHasher` and this hasher does
''not'' raise the `TypeError` on my side:
{{{#!python
In [1]: class Object:
...: def __str__(self):
...: return 'foo'
In [2]: from django.contrib.auth.hashers import get_hasher
In [3]: hasher = get_hasher('default')
In [4]: hasher
Out[4]: <django.contrib.auth.hashers.PBKDF2PasswordHasher at 0x10cef7850>
In [5]: salt = hasher.salt()
In [6]: salt
Out[6]: 'l9QFlyCku6VE'
In [7]: hasher.encode(Object(), salt)
Out[7]:
'pbkdf2_sha256$216000$l9QFlyCku6VE$qqMksofk6MSGevhG/I4xJ7AIRf+Hhq/7myi3pd6vSBU='
In [8]: hasher.encode('foo', salt)
Out[8]:
'pbkdf2_sha256$216000$l9QFlyCku6VE$qqMksofk6MSGevhG/I4xJ7AIRf+Hhq/7myi3pd6vSBU='
}}}
Now I can see two options in order to make this type guard hasher
agnostic:
1. Add if statement to `make_password` as you suggested. Something like:
{{{#!python
if not isinstance(password, (bytes, str)):
raise TypeError('password must be bytes or string (got %s).' %
type(password).__name__)
}}}
2. Change `force_bytes` utility to `to_bytes` and add default keyword
argument `force=True`. Then, hasher's `encode` method would use `to_bytes`
function with `force=False` argument. In all other `force_bytes`
occurrences in the codebase, changing from `force_bytes` to `to_bytes`
should be sufficient.
{{{#!python
def to_bytes(s, encoding='utf-8', strings_only=False, errors='strict',
force=True):
if isinstance(s, bytes):
if encoding == 'utf-8':
return s
else:
return s.decode('utf-8', errors).encode(encoding, errors)
if strings_only and is_protected_type(s):
return s
if isinstance(s, memoryview):
return bytes(s)
if force:
return str(s).encode(encoding, errors)
raise TypeError('cannot convert %s object to bytes' %
type(s).__name__)
}}}
However, this solution would require much more effort and maintaining
backward compatibility. The first option seems to be easier.
--
Ticket URL: <https://code.djangoproject.com/ticket/31375#comment:3>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/068.c9db0803dff5a2a852e4c984a11b71e1%40djangoproject.com.