Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Python hashing and test functions for user passwords stored in OpenLDAP.
#!/usr/bin/env python
"""
http://www.openldap.org/faq/data/cache/347.html
As seen working on Ubuntu 12.04 with OpenLDAP 2.4.28-1.1ubuntu4
Author: Roberto Aguilar <roberto@baremetal.io>
"""
import hashlib
import os
def check_password(tagged_digest_salt, password):
"""
Checks the OpenLDAP tagged digest against the given password
"""
# the entire payload is base64-encoded
assert tagged_digest_salt.startswith('{SSHA}')
# strip off the hash label
digest_salt_b64 = tagged_digest_salt[6:]
# the password+salt buffer is also base64-encoded. decode and split the
# digest and salt
digest_salt = digest_salt_b64.decode('base64')
digest = digest_salt[:20]
salt = digest_salt[20:]
sha = hashlib.sha1(password)
sha.update(salt)
return digest == sha.digest()
def make_secret(password):
"""
Encodes the given password as a base64 SSHA hash+salt buffer
"""
salt = os.urandom(4)
# hash the password and append the salt
sha = hashlib.sha1(password)
sha.update(salt)
# create a base64 encoded string of the concatenated digest + salt
digest_salt_b64 = '{}{}'.format(sha.digest(), salt).encode('base64').strip()
# now tag the digest above with the {SSHA} tag
tagged_digest_salt = '{{SSHA}}{}'.format(digest_salt_b64)
return tagged_digest_salt
if __name__ == '__main__':
# buffer straight out of OpenLDAP
ldap_buf = 'e1NTSEF9VGY1dVFxUkl0VzV2NGowV0RNNXczY2dJd2ZLS0FUcFg='
print 'ldap buffer result: {}'.format(check_password(ldap_buf, 'foobar'))
# check that make_secret() above can properly encode
print 'checking make_secret: {}'.format(check_password(make_secret('foobar'), 'foobar'))
@phihos

This comment has been minimized.

Show comment Hide comment
@phihos

phihos Nov 5, 2013

Thank you very much! It works like a charm. I will use it to make a custom password hashing backend for the django framework.

phihos commented Nov 5, 2013

Thank you very much! It works like a charm. I will use it to make a custom password hashing backend for the django framework.

@hansthen

This comment has been minimized.

Show comment Hide comment
@hansthen

hansthen Aug 13, 2015

Very nice. Thanks.

Very nice. Thanks.

@rompic

This comment has been minimized.

Show comment Hide comment
@rompic

rompic Aug 24, 2016

print 'ldap buffer result: {}'.format(check_password(ldap_buf, 'foobar')) ought to be
print 'ldap buffer result: {}'.format(check_password(ldap_buf.decode('base64'), 'foobar'))

as otherwise assert tagged_digest_salt.startswith('{SSHA}') fails.

rompic commented Aug 24, 2016

print 'ldap buffer result: {}'.format(check_password(ldap_buf, 'foobar')) ought to be
print 'ldap buffer result: {}'.format(check_password(ldap_buf.decode('base64'), 'foobar'))

as otherwise assert tagged_digest_salt.startswith('{SSHA}') fails.

@peppelinux

This comment has been minimized.

Show comment Hide comment
@peppelinux

peppelinux Jan 7, 2018

It works sometimes, sometimes not.
Some strange behaviour with some passwords, for example

ssha_password:    {SSHA}3c/l0uF8MsX4xyk0ui9zvpGCtBVjLrRt
created_password: {SSHA}3c_l0uF8MsX4xyk0ui9zvpGCtBVjLrRt
salt: 632eb46d
password: ciaociao

slapd password is sha_password and password is the secret hashed, with that salt, in "created_password". Very similar not equal!

It works sometimes, sometimes not.
Some strange behaviour with some passwords, for example

ssha_password:    {SSHA}3c/l0uF8MsX4xyk0ui9zvpGCtBVjLrRt
created_password: {SSHA}3c_l0uF8MsX4xyk0ui9zvpGCtBVjLrRt
salt: 632eb46d
password: ciaociao

slapd password is sha_password and password is the secret hashed, with that salt, in "created_password". Very similar not equal!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment