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 /* this is the base64 version of above */
$ ldapsearch -h <host> -b <base> -D <bind> -w <passwd> “(uid=testuser)” userPassword
# extended LDIF
# userPassword:: e01ENX1XaEJlaTUxQTRUS1hnTll1b2laZGlnPT0=