Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django make_password too slow for creating large list of users programatically

I need to create hundreds (possibly thousands) of users programatically in Django. I am using something like:

from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password
for username, email, pwd in big_user_list:
    m = User(username=username, email=email, password=make_password(pwd))
    m.save()

This is taking too long to execute. I've confirmed that make_password is the culprit by running the above script without passwords.

Is there anyway around this slowness issue, I really need this script to execute quickly.

like image 962
Rabih Kodeih Avatar asked Aug 16 '13 12:08

Rabih Kodeih


1 Answers

You could use the django.contrib.auth.hashers.MD5PasswordHasher for an initial password. As per Django docs on how Django stores passwords,

By default, Django uses the PBKDF2 algorithm with a SHA256 hash, a password stretching mechanism recommended by NIST. This should be sufficient for most users: it’s quite secure, requiring massive amounts of computing time to break.

[...]

Django chooses the an algorithm by consulting the PASSWORD_HASHERS setting. This is a list of hashing algorithm classes that this Django installation supports. The first entry in this list (that is, settings.PASSWORD_HASHERS[0]) will be used [by default] to store passwords, and all the other entries are valid hashers that can be used to check existing passwords. [...]

The default for PASSWORD_HASHERS is:

PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
    'django.contrib.auth.hashers.BCryptPasswordHasher',
    'django.contrib.auth.hashers.SHA1PasswordHasher',
    'django.contrib.auth.hashers.MD5PasswordHasher',
    'django.contrib.auth.hashers.CryptPasswordHasher'
)

Thus you'd want to keep the default as it is now, but use a weaker hasher in the beginning; make sure that the MD5PasswordHasher is present in the list. Then use

make_password(pwd, None, 'md5')

to generate a plain salted MD5 password initially; this will not be too weak provided that the initial password is random enough. As the users change their passwords, their passwords will be encrypted with a stronger algorithm.

like image 124