¿Cuál es el formato en el que se almacenan las contraseñas de Django en la base de datos?

Ya sabes cómo se almacenan las contraseñas de django así:

sha1$a1976$a36cc8cbf81742a8fb52e221aaeab48ed7f58ab4 

y ese es el “hashtype $ salt $ hash”. Mi pregunta es, ¿cómo obtienen el $ hash? ¿Es la contraseña y la sal combinadas y luego hash o es algo completamente distinto?

Como siempre, usa la fuente:

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

Como podemos ver, los resúmenes de las contraseñas se realizan concatenando el salt con la contraseña utilizando el algoritmo de hashing seleccionado. luego, el nombre del algoritmo, el salt original y el hash de la contraseña se concatenan, separados por “$” s para formar el resumen.

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

Para validar las contraseñas, django solo verifica que la misma sal y la misma contraseña dan como resultado el mismo resumen.

Según los documentos :

Hashtype es sha1 (predeterminado), md5 o crypt, el algoritmo utilizado para realizar un hash de una sola vía de la contraseña. Salt es una cadena aleatoria utilizada para saltear la contraseña sin formato para crear el hash.

Según el código de 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) 

Como describe la documentación, el hash es el salt, el algoritmo y la contraseña, hash.

Durante mucho tiempo, hasta la versión 1.3, Django siguió la práctica irresponsable de usar una simple iteración simple de SHA1, con un salt que era demasiado corto, para almacenar la información de la contraseña. Ese enfoque ha quedado desactualizado desde 1979 . Cualquier contraseña que se almacene de esa manera es altamente vulnerable al ataque de fuerza bruta. Por razones del motivo, consulte Security Stackexchange sobre hash de contraseñas.

Desde la versión 1.4 en 2012, Django tiene un algoritmo de hashing predeterminado basado en una buena función de derivación de clave estándar, PBKDF2, con un número configurable de iteraciones, cuyo valor predeterminado aumenta con cada versión (20000 en la versión 1.7). También proporciona soporte para bcrypt, y es compatible con versiones anteriores, actualizando automáticamente los hashes de contraseña cuando los usuarios inician sesión. Más información en Administración de contraseñas en Django | Documentación de django