.. index:: django; hash formats

=============================================================
:samp:`passlib.hash.django_{digest}` - Django-specific Hashes
=============================================================

.. currentmodule:: passlib.hash

The `Django <http://www.djangoproject.com>`_ web framework
provides a module for storing user accounts and passwords
(:mod:`!django.contrib.auth`).
This module's password hashing code supports a few simple salted digests,
stored using the format :samp:`{id}${salt}${checksum}` (where :samp:`{id}`
is an identifier assigned by Django).
Passlib provides support for all the hashes used by Django:

* :class:`django_salted_sha1` - simple salted SHA1 digest, currently Django's default.
* :class:`django_salted_md5` - simple salted MD5 digest.
* :class:`django_des_crypt` - support for legacy :class:`des_crypt` hashes,
  shoehorned into Django's hash format.
* :class:`hex_md5` - historical format used by old Django versions.

.. warning::

    All of these hashes are suceptible to brute-force attacks;
    even the strongest of these (:class:`django_salted_sha1`)
    is a simple single-round salted digest.
    They should not be used for any purpose
    besides manipulating existing Django password hashes.

.. seealso::

    * :data:`passlib.apps.django_context` - a premade Django context
      which can read all of the formats listed below.

    * :mod:`passlib.ext.django` - a plugin that
      updates Django to use a stronger hashing scheme,
      and migrates existing hashes as users log in.

Salted Hashes
=============

Usage
-----
These classes can be used directly as follows::

    >>> from passlib.hash import django_salted_sha1 as dss

    >>> #encrypt password
    >>> h = dss.encrypt("password")
    >>> h
    'sha1$c6218$161d1ac8ab38979c5a31cbaba4a67378e7e60845'

    >>> lms.identify(h) #check if hash is recognized
    True
    >>> lms.identify('JQMuyS6H.AGMo') #check if some other hash is recognized
    False

    >>> lms.verify("password", h) #verify correct password
    True
    >>> lms.verify("secret", h) #verify incorrect password
    False

Interface
---------

.. autoclass:: django_salted_md5()
.. autoclass:: django_salted_sha1()

Format
------
An example :class:`!django_salted_sha1` hash (of ``password``) is:

    ``sha1$f8793$c4cd18eb02375a037885706d414d68d521ca18c7``

Both of Django's salted hashes have the same basic format,
:samp:`{ident}${salt}${checksum}`, where:

* :samp:`{ident}` is an identifier (``sha1`` in the case of the example,
  ``md5`` for :class:`!django_salted_md5`).

* :samp:`{salt}` consists of (usually 5) lowercase hexidecimal digits (``f8793`` in the example).

* :samp:`{checksum}` is lowercase hexidecimal encoding of the checksum.

The checksum is generated by concatenating the salt digits followed
by the password, and hashing them using the specified digest (MD5 or SHA-1).
The digest is then encoded to hexidecimal.
If the password is unicode, it is converted to ``utf-8`` first.

Security Issues
---------------
Django's salted hashes should not be considered very secure.

* They use only a single round of digests with known collision
  and pre-image attacks (SHA1 & MD5).

* While it could be increased, they currently use only 20 bits
  of entropy in their salt, which is borderline insufficient to defeat
  rainbow tables.

* They digest the encoded hexidecimal salt, not the raw bytes,
  increasing the odds that a particular salt+password string
  will be present in a pre-computed tables of ascii digests.

Des Crypt
=========

.. autoclass:: django_des_crypt()

Format
------
An example :class:`!django_des_crypt` hash (of ``password``) is
``crypt$cd1a4$cdlRbNJGImptk``; the general format is the same
as the salted hashes: :samp:`{ident}${salt}${checksum}`, where:

* :samp:`{ident}` is the identifier ``crypt``.

* :samp:`{salt}` is 5 lowercase hexidecimal digits (``cd1a4`` in the example).

* :samp:`{checksum}` is a :class:`!des_crypt` hash (``cdlRbNJGImptk`` in the example).

It should be noted that this class essentially just shoe-horns
:class:`des_crypt` into a format compatible with the Django salted hashes (above).
It has a few quirks, such as the fact that only the first two characters
of the salt are used by :class:`!des_crypt`, and they are in turn
duplicated as the first two characters of the checksum.

For security issues relating to :class:`!django_des_crypt`,
see :class:`des_crypt`.

Other Hashes
============

.. autoclass:: django_disabled

.. note::

    Older versions of Django may also have
    passwords encoded using :class:`~passlib.hash.hex_md5`,
    though this has been deprecated by Django.
