glic3rinu / passlib

Automatically exported from code.google.com/p/passlib
Other
15 stars 3 forks source link

ldap_salted_sha1 assumes a salt length of 4 bytes, when sometimes it can be different lengths #30

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Try ldap_salted_sha1.identify on a hash like 
'{SSHA}UDrXYV0JVaVPgiydBmHZpWnHamxsb25nc2FsdA==' ('hello' with a salt of 
'longsalt', made with '{SSHA}' + (sha1('hello' + 'longsalt').digest() + 
'longsalt').encode('base64').strip())
2. See that it returns False

What is the expected output? What do you see instead?

It should return true, and be able to verify passwords against the hash.

What version of the product are you using?

Latest released version from PyPI

Please provide any additional information below.

Different systems generate hashes with different salt lengths, so it would be 
nice to be able to use those with passlib.

Original issue reported on code.google.com by mister...@gmail.com on 7 Apr 2012 at 2:21

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
A fixed version, allowing up to 10 bytes in the salt (some {SSHA} 
implementations use up to 9 bytes for the salt, so I've read).

class ldap_salted_sha1(_SaltedBase64DigestHelper):
    """This class stores passwords using LDAP's salted SHA1 format,
    and follows the :ref:`password-hash-api`.

    It supports a 4-to-10-byte salt.

    The :meth:`encrypt()` and :meth:`genconfig` methods accept the
    following optional keyword:

    :param salt:
        Optional salt string.
        If not specified, one will be autogenerated (this is recommended).
        If specified, it must be a 4-10 byte string; each byte may have any
        value from 0x00 .. 0xff.
    """
    name = "ldap_salted_sha1"
    ident = u"{SSHA}"
    _hash_func = sha1
    _pat = re.compile(ur"^\{SSHA\}(?P<tmp>[+/a-zA-Z0-9=]{32,40})$")
    _stub_checksum = b('\x00') * 20
    min_salt_size = 4
    max_salt_size = 10

    @classmethod
    def from_string(cls, hash):
        if not hash:
            raise ValueError("no hash specified")
        if isinstance(hash, bytes):
            hash = hash.decode('ascii')
        m = cls._pat.match(hash)
        if not m:
            raise ValueError("not a %s hash" % (cls.name,))
        data = b64decode(m.group("tmp").encode("ascii"))
        chk, salt = data[:20], data[20:]
        return cls(checksum=chk, salt=salt, strict=True)

Original comment by mister...@gmail.com on 9 Apr 2012 at 1:17

GoogleCodeExporter commented 9 years ago
Thanks for reporting that... documentation on the real-world use of the LDAP 
hash formats is scarce. As of r89992826f53a, the ldap_salted_(md5|sha1) hash 
formats can now handle variable-length salts. This change should be included in 
Passlib 1.6, which I'm hoping to release in the next week or so.

Original comment by elic@astllc.org on 13 Apr 2012 at 2:04

GoogleCodeExporter commented 9 years ago

Original comment by elic@astllc.org on 13 Apr 2012 at 2:04

GoogleCodeExporter commented 9 years ago
Passlib 1.6 has been released, and includes support for 4-16 byte salts (though 
this can be raised using monkeypatching by setting 
ldap_salted_sha1.max_salt_size). When calling encrypt(), the salt size can be 
set with the 'salt_size=xxx' keyword.

Original comment by elic@astllc.org on 1 May 2012 at 8:53