summaryrefslogtreecommitdiff
path: root/docs/lib/passlib.hash.django_std.rst
blob: c92e5d67d2aa4bec8131d62e1ed23a4dddc387e0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
.. 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 up to and including
Django 1.4

.. seealso::

    * :ref:`passlib.apps.django_context <django-contexts>` -
      a set of premade contexts which mimic Django's builtin hashing policy,
      and 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.

.. _django-1.4-hashes:

Django 1.4 Hashes
=================
Django 1.4 introduced a new "hashers" framework, as well as
three new modern large-salt variable-cost hash algorithms:

* :class:`django_pbkdf2_sha256` - a PBKDF2-HMAC-SHA256 based hash.
* :class:`django_pbkdf2_sha1` - a PBKDF2-HMAC-SHA1 based hash.
* :class:`django_bcrypt` - a wrapper around :class:`~passlib.hash.bcrypt`.

These classes can be used directly as follows::

    >>> from passlib.hash import django_pbkdf2_sha256 as handler

    >>> # encrypt password
    >>> h = handler.encrypt("password")
    >>> h
    'pbkdf2_sha256$10000$s1w0UXDd00XB$+4ORmyvVWAQvoAEWlDgN34vlaJx1ZTZpa1pCSRey2Yk='

    >>> # verify password
    >>> handler.verify("password", h)
    True
    >>> handler.verify("eville", h)
    False

.. seealso:: the generic :ref:`PasswordHash usage examples <password-hash-examples>`

Interface
---------

.. autoclass:: django_pbkdf2_sha256()
.. autoclass:: django_pbkdf2_sha1()
.. data:: django_bcrypt()

    This class implements Django 1.4's BCrypt wrapper, and follows the :ref:`password-hash-api`.

    This is identical to :class:`!bcrypt` itself, but with
    the Django-specific prefix ``"bcrypt$"`` prepended.
    See :doc:`/lib/passlib.hash.bcrypt` for more details,
    the usage and behavior is identical.

    This should be compatible with the hashes generated by
    Django 1.4's :class:`!BCryptPasswordHasher` class.

    .. versionadded:: 1.6

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

    ``pbkdf2_sha256$10000$s1w0UXDd00XB$+4ORmyvVWAQvoAEWlDgN34vlaJx1ZTZpa1pCSRey2Yk=``

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

* :samp:`{ident}` is an identifier (``pbkdf2_sha256`` in the case of the example).

* :samp:`{rounds}` is a variable cost parameter encoded in decimal.

* :samp:`{salt}` consists of (usually 12) alphanumeric digits
  (``s1w0UXDd00XB`` in the example).

* :samp:`{checksum}` is the base64 encoding the PBKDF2 digest.

The digest porition is generated by passing the ``utf-8`` encoded password,
the ``ascii``-encoded salt string, and the number of rounds into
PBKDF2 using the HMAC-SHA256 prf; and generated a 32 byte checksum,
which is then encoding using base64.

The other PBKDF2 wrapper functions similarly.

Django 1.0 Hashes
=================
.. warning::

    All of the following hashes are very susceptible to brute-force attacks;
    since they are simple single-round salted digests.
    They should not be used for any purpose
    besides manipulating existing Django password hashes.

Django 1.0 supports some basic salted digests, as well as some
legacy hashes:

* :class:`django_salted_sha1` - simple salted SHA1 digest, Django 1.0-1.3'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.

These classes can be used directly as follows::

    >>> from passlib.hash import django_salted_sha1 as handler

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

    >>> # verify password
    >>> handler.verify("password", h)
    True
    >>> handler.verify("eville", h)
    False

.. seealso:: the generic :ref:`PasswordHash usage examples <password-hash-examples>`

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 Wrapper
=================

.. 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::

    Some older (pre-1.0) versions of Django encoded
    passwords using :class:`~passlib.hash.hex_md5`,
    though this has been deprecated by Django,
    and should become increasingly rare.