This really perplexed me and took an embarrassingly long time to write such a simple method. Maybe these notes will save someone else some frustration. Here is a method to generate an MD5 hashed password to use as the value of the userPassword attribute in LDAP:
String hashMD5Password(String password) throws NoSuchAlgorithmException, UnsupportedEncodingException { MessageDigest digest = MessageDigest.getInstance("MD5"); digest.update(password.getBytes("UTF8")); String md5Password = Base64.encode(digest.digest()); return "{MD5}" + md5Password; }
A few tips that might be of help:
- Code that is almost exactly the same as this is posted elsewhere, without the {MD5} prefix that is particular to LDAP. Don’t forget it!
- I use Base64 from jcifs.util.Base64 (since I also use jcifs to generate passwords for the sambaNTPassword attribute) but there are several Base64 classes to choose from.
- Your LDAP server may use another form of encryption (CRYPTO, SHA, etc.). It should be a simple matter to adapt the method above to use other encryption types.
Had I known the following, this would have been so much easier:
- The format of the userPassword attribute is a string containing the crypto-identifier (ie. {MD5}) followed by the Base64-encoded MD5 digest version of the plain-text password
- Verify the output of the java method by running “slappasswd -h {MD5} -s your_password. The output of this command should match the string returned by the java method but not the string returned by ldapquery.
- ldapquery returns LDIF, so the userPassword value is further Base64-encoded.
To illustrate these last few points, consider the following:
$ slappasswd -h {MD5} -s test1 {MD5}WhBei51A4TKXgNYuoiZdig== /* this is what is stored in LDAP) */ $ slappasswd -h {MD5} -s test1 | base64 e01ENX1XaEJlaTUxQTRUS1hnTll1b2laZGlnPT0K /* base64 version of above */ $ ldapsearch -h <host> -b <base> -D <bind> -w <passwd> "(uid=testuser)" userPassword # extended LDIF # userPassword:: e01ENX1XaEJlaTUxQTRUS1hnTll1b2laZGlnPT0=
Hi,
Can you share the code you use to generate the sambaNTPassword attribute?
Thanks in advance
Sure thing – here’s the code I use to set both the UNIX and SMB/NTLM password in LDAP from the same plaintext password: https://gist.github.com/abythell/4757703. It uses the Unbound LDAP SDK to read/write LDAP, and JCIFS for generating the NTLM hash.
Thanks a lot!
this line don´t works
String md5Password = Base64.encode(digest.digest());
It require byte[] not a String.
any idea?
Verify which package is providing your Base64 class, as there are a few choices. Here I’m using jcifs.util.Base64, not org.apache.commons.codec.binary. See https://gist.github.com/abythell/4757703 for a complete, working example.