20090910 more fun with hashed and encoded strings - plembo/onemoretech GitHub Wiki

title: More fun with hashed and encoded strings link: https://onemoretech.wordpress.com/2009/09/10/more-fun-with-hashed-and-encoded-strings/ author: lembobro description: post_id: 250 created: 2009/09/10 21:04:43 created_gmt: 2009/09/10 21:04:43 comment_status: open post_name: more-fun-with-hashed-and-encoded-strings status: publish post_type: post

More fun with hashed and encoded strings

Most of us who have worked with LDAP directories know that the better systems out there don’t actually store passwords in user entries.

Paragraph 5.36 of RFC 2256 specified that the userpassword attribute be stored using the octet string syntax and not encrypted.

Early on it became the practice to have the directory server itself hash an incoming password and commit that hashed value to the directory. By far the most popular method is to hash using the SHA-1 or SSHA algorithm and encode the result as a Base64 string. Further obfuscation is provided by Base64 re-encoding the string again. Subsequent authentication attempts are handled by comparing the stored hash to the text submitted by applying the same hashing and encoding algorithm to that text and seeing if it matches the stored value.

As with all things, it helps to see this illustrated. The following bit of perl code will let you take a text string of your choice and see the results of hashing and Base64 encoding that string.

`

#!/usr/bin/perl
use strict;
use Digest::SHA qw(sha1_base64);
use MIME::Base64;
	
my $data = "purple";
	
print "Original text: ", $data, "n";
	
my $hashed = sha1_base64($data);
print "Hashed text: ", $hashed, "n";
	
my $shatext = '{SHA}' . $hashed . '=';
print "Formatted hash: ", $shatext, "n";
	
my $encoded = encode_base64($shatext);
print "Base64 re-encoded: ", $encoded, "n";
	
my $decoded = decode_base64($encoded);
print "Decoded: ", $decoded, "n";
	
__END__;

`

Here’s the output:

Original text: purple
Hashed text: r67XVAa9QUggzqSlEZ+QwlnAV1U
Formatted hash: {SHA}r67XVAa9QUggzqSlEZ+QwlnAV1U=
Base64 re-encoded: e1NIQX1yNjdYVkFhOVFVZ2d6cVNsRVorUXdsbkFWMVU9
Decoded: {SHA}r67XVAa9QUggzqSlEZ+QwlnAV1U=

What you’ll find is that when you query a directory as a privileged user (e.g. “cn=Directory Manager”) for the userpassword in an entry, most LDAP utilities will return either the formatted hash (e.g. with the “{SHA}” prepended and an equals sign at the end), or the Base64 re-encoded value.

As you can see from the code above, translating a string into a Base64 encoded SHA hash and then further Base64 encoding the result isn’t difficult using a combination of the Digest::SHA and MIME::Base64 perl modules. Decoding the Base64 encoded result back into the formatted Base64 SHA hash is also pretty straightforward. Note that the Digest::SHA module doesn’t automatically add the “{SHA}” prefix or “=” suffix to the hash value, so that needs to be done “manually” inside the script.

The hashed text is as far back in the process as you can go, since this is a one-way hash by design. But with the value in either formatted or Base64 re-encoded form you will be able to compare it to existing values stored in entry userpassword attributes. One application for this is a script that goes out and compares userpassword values to the kinds of insecure password strings that we always warn users to avoid. A “dictionary” of values can be built by hashing a list of words and then comparing the results with the hash values in entry userpassword attributes.

Note: Using Gisle Aas’s Digest::SHA1 module will give the same results demonstrated here. The major difference between Gisle’s module and Mark Shelor’s Digest::SHA is that the latter allows the use of some stronger SHA-based algorithms.

Copyright 2004-2019 Phil Lembo