I want to implement a comparison-function with ldap3 in Python that can compare a user-given value with a password stored in my ldap-entry.
This is easy to do with non-salted passwords but I'm struggling with salted ones. For example, the stored password in my ldap-entry looks like this:
{SSHA}F5GwOd39wiK+jEKD6UwCs+9XvzvdRYlX
and represents the Salted SHA value of
testpassword
I do not want to check the value with a bind because there might be more than one password saved in the entry. A bind would only check if the user-given value is indeed one of the passwords, and not the password I want to compare it to.
Edit: I want to do this in a LDAP-Editor. A function like this is already implemented in the LDAP-Editor I'm currently using (LDAP Account Manager / LAM). This comparison is not there to handle a login of some sort, it is there so the user himself can check if the password matches his user-given value.
This would be perfect for entries that have more than one password (yes, that is possible) and you have to delete one of them. Of course you could delete all values and add back the ones you still want to use. A comparison would be handy here because the step of deleting every password and adding all the ones back that are still in use would be skipped.
If there is anything else to clarify, I can elaborate more.
Any help is appreciated!
The LDAP faq-o-matic explains how to generate SSHA password hashes). Using that information, we know how to extract the salt from the SSHA password, which then allows us to hash our test password using the same salt to see if we get the same digest:
import sys
import base64
import hashlib
SSHA_TAG = '{SSHA}'
def salt_from_ssha(pw):
if pw.startswith(SSHA_TAG):
pw = pw[len(SSHA_TAG):]
dec = base64.b64decode(pw)
digest, salt = dec[:20], dec[20:]
return digest, salt
def compare_password_with_hashed_password(hashed_password, plaintext_password):
digest, salt = salt_from_ssha(hashed_password)
plaintext_hash = hashlib.sha1(plaintext_password + salt)
return plaintext_hash.digest() == digest
target = sys.argv[1]
while True:
testpw = input("Enter a test password: ").encode()
if compare_password_with_hashed_password(target, testpw):
print("You found it!")
break
Running this might look like:
$ py hasher.py {SSHA}F5GwOd39wiK+jEKD6UwCs+9XvzvdRYlX
Enter a test password: foo
Enter a test password: bar
Enter a test password: testpassword
You found it!