Каков формат, в котором пароли Django хранятся в базе данных?
Вы знаете, как пароли django хранятся следующим образом:
sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4
и это "hashtype $salt $hash". Мой вопрос в том, как они получают $хэш? Является ли это паролем и солью, а затем хэшируется или что-то еще?
Ответы
Ответ 1
Как всегда, используйте источник:
# root/django/trunk/django/contrib/auth/models.py
# snip
def get_hexdigest(algorithm, salt, raw_password):
"""
Returns a string of the hexdigest of the given plaintext password and salt
using the given algorithm ('md5', 'sha1' or 'crypt').
"""
raw_password, salt = smart_str(raw_password), smart_str(salt)
if algorithm == 'crypt':
try:
import crypt
except ImportError:
raise ValueError('"crypt" password algorithm not supported in this environment')
return crypt.crypt(raw_password, salt)
if algorithm == 'md5':
return md5_constructor(salt + raw_password).hexdigest()
elif algorithm == 'sha1':
return sha_constructor(salt + raw_password).hexdigest()
raise ValueError("Got unknown password algorithm type in password.")
Как мы видим, дайджесты паролей выполняются путем объединения соли с паролем с использованием выбранного алгоритма хэширования. то имя алгоритма, исходная соль и хэш пароля объединяются, разделяются "$" для формирования дайджеста.
# Also from root/django/trunk/django/contrib/auth/models.py
def check_password(raw_password, enc_password):
"""
Returns a boolean of whether the raw_password was correct. Handles
encryption formats behind the scenes.
"""
algo, salt, hsh = enc_password.split('$')
return hsh == get_hexdigest(algo, salt, raw_password)
Чтобы проверить пароли, django просто проверяет, что одна и та же соль и один и тот же пароль приводят к одному и тому же дайджесту.
Ответ 2
В соответствии с документами:
Hashtype - это либо sha1 (по умолчанию), либо md5, либо crypt - алгоритм, используемый для выполнения одностороннего хэша пароля. Соль - это случайная строка, используемая для солевого сырого пароля для создания хэша.
В соответствии с кодом set_password
:
def set_password(self, raw_password):
import random
algo = 'sha1'
salt = get_hexdigest(algo, str(random.random()), str(random.random()))[:5]
hsh = get_hexdigest(algo, salt, raw_password)
self.password = '%s$%s$%s' % (algo, salt, hsh)
Как описано в документации, хеш - это соль, алгоритм и пароль, хешированный.
Ответ 3
В течение долгого времени, вплоть до версии 1.3, Django действительно следовал безответственной практике использования простой одиночной итерации SHA1 с солью, которая была слишком короткой, для хранения информации о пароле. Этот подход был устаревшим с 1979 года. Любые пароли, хранящиеся таким образом, очень уязвимы для атаки грубой силы. По причинам, см. Безопасность Stackexchange при хешировании паролей
Начиная с версии 1.4 в 2012 году, Django имеет алгоритм хэширования по умолчанию, основанный на хорошей стандартной функции деривации ключей PBKDF2 с настраиваемым числом итераций, значение по умолчанию увеличивается с каждой версией (20000 в версии 1.7). Он также обеспечивает поддержку bcrypt и обратно совместим с более ранними версиями, автоматически обновляя хэши паролей, когда пользователи входят в систему. Подробнее см. Управление паролями в Django | Документация Django