#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.

Reply via email to