13-1-3 password management

Time:2021-2-25

Password management in Django

Password management is not reinvented when it is not necessary. Django is committed to providing a set of secure and flexible tools to manage user passwords. This document describes how Django stores passwords and hash storage method configurations, as well as some examples of using hash passwords.

See also

Even if users may use strong passwords, attackers may eavesdrop on their connections. use_HTTPS_To avoid sending the password (or any sensitive data) on the HTTP connection, because otherwise the password will be sniffed.

How do Django store passwords

Django usually uses pbkdf2 to provide a flexible password storage system.

UserObjectpasswordProperty is a string in this format:

<algorithm>$<iterations>$<salt>$<hash>

Those are the parts used to store user passwords, separated by dollar characters. They are composed of hash algorithm, algorithm iteration times (work factor), random salt and generated password hash value. Algorithm is Django can use, one-way hash or password storage algorithm, see below. Iteration describes the number of times the algorithm is executed on the hash. Salt is a random seed value, and the hash value is the result of this one-way function.

Django is usually used as a hash of sha256PBKDF2Algorithm, byNISTA recommended password scaling mechanism. This works for most users: it’s very secure and requires a lot of computing to crack.

However, depending on your needs, you can choose a different algorithm, or even use a custom algorithm to meet your specific security environment. However, most users don’t need to do that – if you’re not sure, it’s better not. If you plan to do so, read on:

Django throughPASSWORD_HASHERSSet to select the algorithm to use. Here is a list of hash algorithm classes supported by Django. The first element of the list (i.esettings.PASSWORD_HASHERSAll other elements are hash values for verification, which can be used to check existing passwords. It means that if you plan to use a different algorithm, you need to modify it[PASSWORD_HASHERSTo put your favorite algorithm at the top of the list.

PASSWORD_HASHERSThe default value is:

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

This means that Django will usePBKDF2All passwords are stored, but pbkdf2sha1 is supported,bcrypt, SHA1And so on algorithm to check the stored password. The next section describes some common methods that advanced users may want to use to modify this setting.

Using bcrypt in Django

BcryptIs a popular password storage algorithm, which is specially designed for long-term password storage. Django does not use it by default, because it needs to use three-party libraries, but because many people want to use it, Django will support it with minimal effort.

Perform the following steps to use bcrypt as your default storage algorithm:

  1. installBcrypt Library. This can be done by running thepip install django[bcrypt], or download and runpython setup.py installTo achieve.

  2. modifyPASSWORD_HASHERS, willBCryptSHA256PasswordHasherFirst of all. In other words, in your settings file, you should:

    PASSWORD_HASHERS = (
        'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
        'django.contrib.auth.hashers.BCryptPasswordHasher',
        'django.contrib.auth.hashers.PBKDF2PasswordHasher',
        'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
        'django.contrib.auth.hashers.SHA1PasswordHasher',
        'django.contrib.auth.hashers.MD5PasswordHasher',
        'django.contrib.auth.hashers.CryptPasswordHasher',
    )
    
(you should leave other elements in the list, otherwise Django can't upgrade the password; see below).

Configuration complete – Django will now use bcrypt as the default storage algorithm.

Bcryptpasswordhasher’s password truncation

Bcrypt’s designers truncate all passwords at 72 characters, which meansbcrypt(password_with_100_chars) == bcrypt(password_with_100_chars[:72]). NativeBCryptPasswordHasherIt will not do any special processing, so it will also be constrained by the length limit of the hidden password.BCryptSHA256PasswordHasherThis problem can be solved by using sha256 to generate hash in advance. This will prevent password truncation, so you should give priority to itBCryptPasswordHasher. The actual effect of this truncation is negligible, because most users will not use a password longer than 72 characters, and even if it is truncated at 72 characters, the computing power required to crack brypt is still astronomical. Nevertheless, we recommend itBCryptSHA256PasswordHasherAccording to the principle of “be prepared for no danger”.

Implementation of other bcrypt

There are other bcrypt implementations that you can use in Django. Django’s bcrypt support is not directly compatible with these implementations. You need to change the hash value in the database tobcrypt$(raw bcrypt output)To upgrade them. For example:bcrypt$$2a$12$NT0I31Sa7ihGEWpka9ASYrEFkhuTNeBQ2xfZskIiiJeyFXhRgS.Sy

Increase work factor

Pbkdf2 and bcrypt algorithms use a lot of hash iterations or loops. This will deliberately slow down the attacker, making the hash password attack more difficult. However, with the increasing of computer ability, the number of iterations also needs to increase. We’ve chosen a reasonable default (and it’s increasing with every Django release), but you may want to turn it up or down, depending on your security needs and computing power. To do this, you can inherit the corresponding algorithm and override ititerationsParameters. For example, increase the number of iterations used by pbkdf2 algorithm by default

  1. establishdjango.contrib.auth.hashers.PBKDF2PasswordHasherSubclass of:

    from django.contrib.auth.hashers import PBKDF2PasswordHasher
    
    class MyPBKDF2PasswordHasher(PBKDF2PasswordHasher):
        """
        A subclass of PBKDF2PasswordHasher that uses 100 times more iterations.
        """
        iterations = PBKDF2PasswordHasher.iterations * 100
    
Save it somewhere in the project. For example, put it in a location similar to ` myproject '/ hashers.py `In the file.
  1. Add your new hash as the first element to thePASSWORD_HASHERS

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

Configuration complete – now Django will use more iterations when storing passwords using pbkdf2.

Password upgrade

After users log in, Django will automatically upgrade the algorithm to the preferred one if their password is not stored in the preferred one. This means that old installations in Django will automatically become more secure when users log in, and you can switch to new (or better) storage algorithms whenever they are invented.

However, Django will only upgrade inPASSWORD_HASHERSSo when you upgrade to a new system, you should make sure that you don’t_ Remove_ Elements in the list. If you remove it, users who use algorithms that are not in the list will not be upgraded. After modifying the number of pbkdf2 iterations, the password will also be upgraded.

Manually managing a user’s password

django.contrib.auth.hashersThe module provides a series of functions to create and verify hash passwords. You can be independent ofUserUse them outside of the model.

check_password(_password_, _encoded_)[source]

If you plan to manually authenticate users by comparing plain text passwords with hashed passwords in the database, usecheck_password()This is a convenient function. It receives two parameters: the plain text password to check, and the password of the user in the databasepasswordThe full value of the field. If they match, returnTrueOtherwise, returnFalse

make_password(_password_, _salt=None_, _hasher=’default’_)[source]

Creates a hash password in the format used by the current application. It takes a required parameter: plain text password. If you don’t want to use the default(PASSWORD_HASHERSYou can provide the salt value and the hash algorithm to use, which are optional. The current algorithms are as follows:'pbkdf2_sha256', 'pbkdf2_sha1', 'bcrypt_sha256'(see_ Using bcrypt in Django_), 'bcrypt', 'sha1', 'md5', 'unsalted_md5'(for backward compatibility only) and'crypt'(if you installcryptLibrary). If the password parameter isNone, will return an unavailable password (it will never be used)check_password()Accept).

is_password_usable(_encoded_password_)[source]

Check whether the string provided is usablecheck_password()The hash password to verify.

translator:Django document collaborative translation teamOriginal text:Password management

This paper is based onCC BY-NC-SA 3.0Please keep the author’s signature and the source of the article.

Django document collaborative translation teamWe are short of staff. Interested friends can join us. It is totally public welfare. Communication group: 467338606.