summaryrefslogtreecommitdiff
path: root/docs/lib/passlib.hash.des_crypt.rst
blob: 350fbac8c82ebed516a2c20a915cec9cc74e6a91 (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
=======================================================================
:mod:`passlib.hash.des_crypt` - Tradtional Unix DES Crypt
=======================================================================

.. module:: passlib.hash.des_crypt
    :synopsis: Traditional Unix (DES) Crypt

.. warning::

    This algorithm is extremely weak by modern standards,
    and should not be used for new applications.
    It suffers from it's use of the DES cipher, a small number of salt bits,
    and fact that it uses only the first 8 characters of the password.

This module implements the original DES-based Unix Crypt algorithm.
While no longer in active use, it is supported for legacy purposes
by many unix variants.

Usage
=====
This module can be used directly as follows::

    >>> from passlib.hash import des_crypt as dc

    >>> dc.encrypt("password") #generate new salt, encrypt password
    'JQMuyS6H.AGMo'
    >>> dc.genhash("password", "JQ") #generate password using existing config string
    'JQMuyS6H.AGMo'

    >>> dc.identify('JQMuyS6H.AGMo') #check if hash is recognized
    True
    >>> dc.identify('$1$3azHgidD$SrJPt7B.9rekpmwJwtON31') #check if hash is recognized
    False

    >>> dc.verify("password", 'JQMuyS6H.AGMo') #verify password
    True
    >>> dc.verify("secret", 'JQMuyS6H.AGMo') #verify password
    False

Functions
=========
.. autofunction:: genconfig
.. autofunction:: genhash
.. autofunction:: encrypt
.. autofunction:: identify
.. autofunction:: verify

Format
======
A des-crypt hash string consists of 13 characters, drawn from ``[./0-9A-Za-z]``.
The first 2 characters form a :mod:`hash64 <passlib.utils.h64>`-encoded
12 bit integer used as the salt, with the remaining characters
forming a hash64-encoded 64-bit integer checksum.

A des-crypt configuration string is also accepted by this module,
consists of only the first 2 characters, corresponding to the salt only.

An example hash (of ``password``) is ``JQMuyS6H.AGMo``, where the salt is ``JQ``, and the checksum ``MuyS6H.AGMo``.

Algorithm
=========
The checksum is formed by a modified version of the DES cipher in encrypt mode:

* First, the lower 7 bits of the first 8 characters of the password are used
  to form a 56-bit DES key. The remainder of the password is ignored.

* The checksum is then generated by recursively performing 25 rounds of DES encryption
  starting with a null input block. The 12 bits of salt are used to mutate
  the action performed by each block of the DES key schedule (see the source
  of :func:`~passlib.utils.des.mdes_encrypt_int_block` for details).

* The checksum and salt are then encoded according the format, as described above.

Deviations
==========
This implementation of des-crypt differs from others in a few ways:

* Before generating a hash, PassLib encodes unicode passwords using UTF-8.
  The original des-crypt was designed for 7-bit us-ascii, so this should not
  conflict with most existing hashes. As of this writing, the authors
  know of no specification defining the official behavior that should be used
  in this situtation.

* Some implementations (eg: linux) accept empty and single-character salt strings,
  as well as salt strings containing other characters. The behavior for these
  implementations is not immediately obvious, desirable, and/or correct.
  Lacking even a de facto standard, this implementation will throw
  a "invalid salt" ValueError for such inputs.

References
==========
* `<http://www.dynamic.net.au/christos/crypt/UnixCrypt2.txt>`_ - java implementation of des-crypt, used as base for pure-python implementation