(Answer) (Category) OpenLDAP Faq-O-Matic : (Category) OpenLDAP Software FAQ : (Category) Configuration : (Category) SLAPD Configuration : (Category) Passwords : (Answer) What are {SHA} and {SSHA} passwords and how do I generate them?
OpenLDAP supports RFC 2307 passwords, including the {SHA}, {SSHA} and other schemes. Such passwords may be used as userPassword values and/or rootpw value. See (Xref) What are RFC 2307 hashed user passwords?.
{SHA} and {SSHA} are RFC 2307 passwords schemes which use the SHA1 secure hash algorithm. The {SSHA} is the seeded varient. {SSHA} is recommended over other RFC 2307 schemes.

Netscape provides a technical note on how to generate {SHA} and {SSHA} password values. See: http://developer.netscape.com:80/docs/technote/ldap/pass_sha.html

#! /usr/bin/perl
#
# This small script generates an Seeded SHA1 hash of 'secret'
# (using the seed "salt") for use as a userPassword or rootpw value.
#
use Digest::SHA1;
use MIME::Base64;
$ctx = Digest::SHA1->new;
$ctx->add('secret');
$ctx->add('salt');
$hashedPasswd = '{SSHA}' . encode_base64($ctx->digest . 'salt' ,'');
print 'userPassword: ' .  $hashedPasswd . "\n";
#! /usr/bin/perl
#
# This small script generates an SHA1 hash of 'secret' for use
# as a userPassword or rootpw value.
#
use Digest::SHA1;
use MIME::Base64;
$ctx = Digest::SHA1->new;
$ctx->add('secret');
$hashedPasswd = '{SHA}' . encode_base64($ctx->digest,'');
print 'userPassword: ' .  $hashedPasswd . "\n";
When generating passwords in PHP, some confusion may occur.
First of all, make use of the 'slappasswd' utility to generate a password, so you can check if your PHP routines are correct. (The slappasswd utility is part of the openldap distribution).
The command
        slappasswd -h {SHA} -s abcd123
will generate
        {SHA}fDYHuOYbzxlE6ehQOmYPIfS28/E=
so, in your entry, an attribute like this could be specified:
        userPassword: {SHA}fDYHuOYbzxlE6ehQOmYPIfS28/E=
but when you do a slapcat or ldapsearch and the output is in LDIF format, the userpassword will be base_64 encoded, and it will look like this:
        userPassword:: e1NIQX1mRFlIdU9ZYnp4bEU2ZWhRT21ZUElmUzI4L0U9
Confused yet ?
Now enter PHP (< 5). You would like to generate a {SHA} password from a cleartext password that was entered in a FORM by a user, which is held in $pass. It would be easy to do:
        $userpassword = "{SHA}" . sha1( $pass );
but that will generate:
        {SHA}7c3607b8e61bcf1944e9e8503a660f21f4b6f3f1
and altough that looks nice, it won't work. That's because the PHP sha1() function delivers a Hex encoded string. In PHP >= 5 you can set a boolean, to omit that:
        $userpassword = "{SHA}" . sha1( $pass, TRUE );
but in PHP < 5 you need to do this:
        $userpassword = "{SHA}" . pack( "H*", sha1( $pass ) );
this will generate:
        something very ugly that I can't represent here, since it is binary.
now to avoid putting the binary stuff into the directory, you need to base_64 encode it, like this:
        $userpassword = "{SHA}" . base64_encode( pack( "H*", sha1( $pass ) ) ); 
this will, finally, generate
        {SHA}fDYHuOYbzxlE6ehQOmYPIfS28/E=
and that value should be put into the userPassword attribute.
Ace (http://www.qwido.net)


#!/usr/bin/env ruby
# Ruby script to generate SSHA (Good for LDAP)
require 'sha1'
require 'base64'
hash = "{SSHA}"+Base64.encode64(Digest::SHA1.digest('secret'+'salt')+'salt').chomp!
puts 'userPassword: '+hash+"\n"
Ruby script to generate SSHA:
#!/usr/bin/env ruby
require 'sha1' require 'base64' hash = "{SSHA}"+Base64.encode64(Digest::SHA1.digest('secret'+'salt')+'salt').chomp! puts 'userPassword: '+hash+"\n"
SHA passwords in Python:
import sha from base64 import b64encode ctx = sha.new( password ) hash = "{SHA}" + b64encode( ctx.digest() )
And salted SHA (guessing from the perl-examples, haven't tried it):
import sha from base64 import b64encode ctx = sha.new( password ) ctx.update( salt ) hash = "{SSHA}" + b64encode( ctx.digest() + salt )

2008/01/10 - Reed O'Brien

SSHA python seeded salted sha password

import hashlib
from base64 import urlsafe_b64encode as encode
from base64 import urlsafe_b64decode as decode

def makeSecret(password):
    salt = os.urandom(4)
    h = hashlib.sha1(password)
    h.update(salt)
    return "{SSHA}" + encode(h.digest() + salt)

def checkPassword(challenge_password, password):
    challenge_bytes = decode(challenge_password[6:])
    digest = challenge_bytes[:20]
    salt = challenge_bytes[20:]
    hr = hashlib.sha1(password)
    hr.update(salt)
    return digest == hr.digest()


>>> challenge_password = makeSecret('testing123')

>>> challenge_password
    '{SSHA}0c0blFTXXNuAMHECS4uxrj3ZieMoWImr'

>>> checkPassword(challenge_password, 'testing123')
    True

>>> checkPassword(challenge_password, 'testing124')
    False
Previous Python method to generate SHA and SSHA password is wrong and works partially with openldap, don't use urlsafe_b64encode
from base64 module who replace "/" by _ and "+" by "-". Use instead the encodestring method from the same module.

So the previous code is : 

import hashlib
from base64 import encodestring as encode
from base64 import decodestring as decode

def makeSecret(password):
    salt = os.urandom(4)
    h = hashlib.sha1(password)
    h.update(salt)
    return "{SSHA}" + encode(h.digest() + salt)

def checkPassword(challenge_password, password):
    challenge_bytes = decode(challenge_password[6:])
    digest = challenge_bytes[:20]
    salt = challenge_bytes[20:]
    hr = hashlib.sha1(password)
    hr.update(salt)
    return digest == hr.digest()
Note that base64.encodestring() appends a newline ("\n") to its output (see http://docs.python.org/library/base64.html), so makeSecret() should probably be modified to strip that newline:

def makeSecret(password):
    salt = os.urandom(4)
    h = hashlib.sha1(password)
    h.update(salt)
    return "{SSHA}" + encode(h.digest() + salt){:-1]
Forgive the formatting errors and typos in my previous edit. Here's what I meant to write 
(note change from open brace to open bracket in to the last line):

Note that base64.encodestring() appends a newline ("\n") to its output (see http://docs.python.org/library/base64.html), 
so makeSecret() should probably be modified to strip that newline:

def makeSecret(password):
    salt = os.urandom(4)
    h = hashlib.sha1(password)
    h.update(salt)
    return "{SSHA}" + encode(h.digest() + salt)[:-1]
If you are stuck on Windows, using the OpenSSL for Windows package: http://gnuwin32.sourceforge.net/packages/openssl.htm

The below batch script can generate a {SHA} hash suitable for LDAP passwords:

makeshahash.bat:
@echo off
echo|set /p="{SHA}"
echo|set /p="%1" | openssl dgst -sha1 -binary | openssl enc -base64

> makeshahash.bat secret
{SHA}5en6G6MezRroT3XKqkdPOmY/BfQ=
Here is an update for Python-based hashing and testing.  These functions worked on
Ubuntu 12.04 + OpenLDAP 2.4.28-1.1ubuntu4.

https://gist.github.com/rca/7217540

Thanks!
[Append to This Answer]
Previous: (Answer) Which RFC 2307 password schemes are recommended and why?
Next: (Answer) What are {MD5} and {SMD5} passwords and how do I generate them?
This document is: http://www.openldap.org/faq/index.cgi?file=347
[Search] [Appearance]
This is a Faq-O-Matic 2.721.test.
© Copyright 1998-2013, OpenLDAP Foundation, info@OpenLDAP.org