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
|
=============================================================
:samp:`passlib.hash.ldap_{digest}` - RFC2307 Standard Digests
=============================================================
.. currentmodule:: passlib.hash
Passlib provides support for all the standard
LDAP hash formats specified by :rfc:`2307`.
This includes ``{MD5}``, ``{SMD5}``, ``{SHA}``, ``{SSHA}``.
These schemes range from somewhat to very insecure,
and should not be used except when required.
.. note::
RFC 2307 also specifies a ``{CRYPT}`` scheme,
which is supposed to wrap the host OS's :func:`!crypt()`.
Being host-dependant, this scheme is somewhat different,
and is details in :doc:`passlib.hash.ldap_crypt`.
.. seealso::
* :doc:`passlib.hash.ldap_crypt`
* :mod:`!passlib.apps` for a :ref:`list of premade ldap contexts <ldap-contexts>`.
Usage
=====
These classes all wrap the underlying hashlib implementations,
and are mainly useful only for plugging them into a :class:`~passlib.context.CryptContext`.
However, they can be used directly as follows::
>>> from passlib.hash import ldap_salted_md5 as lsm
>>> #encrypt password
>>> h = lsm.encrypt("password")
>>> h
'{SMD5}OqsUXNHIhHbznxrqHoIM+ZT8DmE='
>>> 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
Plain Hashes
============
.. warning::
These hashes should be considered secure in any manner,
as they are nothing but raw MD5 & SHA-1 digests,
which are extremely vulnerable to brute-force attacks.
.. autoclass:: ldap_md5()
.. autoclass:: ldap_sha1()
Format
------
These hashes have the format :samp:`{prefix}{checksum}`.
* :samp:`{prefix}` is `{MD5}` for ldap_md5, and `{SHA}` for ldap_sha1.
* :samp:`{checksum}` is the base64 encoding
of the raw message digest of the password,
using the appropriate digest algorithm.
An example ldap_md5 hash (of ``password``) is ``{MD5}X03MO1qnZdYdgyfeuILPmQ==``.
An example ldap_sha1 hash (of ``password``) is ``{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=``.
Salted Hashes
=============
.. autoclass:: ldap_salted_md5()
.. autoclass:: ldap_salted_sha1()
These hashes have the format :samp:`{prefix}{data}`.
* :samp:`{prefix}` is `{SMD5}` for ldap_salted_md5,
and `{SSHA}` for ldap_salted_sha1.
* :samp:`{data}` is the base64 encoding of :samp:`{checksum}{salt}`;
and in turn :samp:`{salt}` is a multi-byte binary salt,
and :samp:`{checksum}` is the raw digest of the
the string :samp:`{password}{salt}`,
using the appropriate digest algorithm.
Format
------
An example hash (of ``password``) is ``{SMD5}jNoSMNY0cybfuBWiaGlFw3Mfi/U=``.
After decoding, this results in a raw salt string ``s\x1f\x8b\xf5``,
and a raw MD5 checksum of ``\x8c\xda\x120\xd64s&\xdf\xb8\x15\xa2hiE\xc3``.
An example hash (of ``password``) is ``{SSHA}pKqkNr1tq3wtQqk+UcPyA3HnA2NsU5NJ``.
After decoding, this results in a raw salt string ``lS\x93I``,
and a raw SHA1 checksum of ``\xa4\xaa\xa46\xbdm\xab|-B\xa9>Q\xc3\xf2\x03q\xe7\x03c``.
Security Issues
---------------
The LDAP 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).
* They currently use only 32 bits of entropy in their salt,
which is only borderline sufficient to defeat rainbow tables,
and cannot (portably) be increased.
Plaintext
=========
.. autoclass:: ldap_plaintext()
This handler does not hash passwords at all,
rather it encoded them into UTF-8.
The only difference between this class and :class:`~passlib.hash.plaintext`
is that this class will NOT recognize any strings that use
the ``{SCHEME}HASH`` format.
Deviations
==========
* The salt size for the salted digests appears to vary between applications.
While OpenLDAP is fixed at 4 bytes, some systems appear to use 8 or more.
Passlib can accept and generate strings with salts between 4-16 bytes,
though various servers may differ in what they can handle.
.. rubric:: Footnotes
.. [#pwd] The manpage for :command:`slappasswd` - `<http://gd.tuwien.ac.at/linuxcommand.org/man_pages/slappasswd8.html>`_.
.. [#rfc] The basic format for these hashes is laid out in RFC 2307 - `<http://www.ietf.org/rfc/rfc2307.txt>`_
.. [#] OpenLDAP hash documentation - `<http://www.openldap.org/doc/admin24/security.html>`_
|