views:

134

answers:

1

I'm working on a Python script to create hashed strings from an existing system similar to that of ASP.NET's MembershipProvider. Using Python, is there a way to take a hexadecimal string and convert it back to a binary and then do a base64 encoding, somehow treating the original string as Unicode. Let's try some code. I'm looking to re-encode a hashed password so that the hashes would be equal in Python and ASP.NET/C#:

import base64
import sha
import binascii

def EncodePassword(password):
    # strings are currently stored as hex
    hex_hashed_password = sha.sha(password).hexdigest()

    # attempt to convert hex to base64
    bin_hashed_password = binascii.unhexlify(hex_hashed_password)
    return base64.standard_b64encode(bin_hashed_password)

print EncodePassword("password")
# W6ph5Mm5Pz8GgiULbPgzG37mj9g=

The ASP.NET MembershipProvider users this method to encode:

static string EncodePassword(string pass)
{
    byte[] bytes = Encoding.Unicode.GetBytes(pass);
    //bytes = Encoding.ASCII.GetBytes(pass);

    byte[] inArray = null;
    HashAlgorithm algorithm = HashAlgorithm.Create("SHA1");
    inArray = algorithm.ComputeHash(bytes);
    return Convert.ToBase64String(inArray);
}

string s = EncodePassword("password");
// 6Pl/upEE0epQR5SObftn+s2fW3M=

That doesn't match. But, when I run it with the password encoded with ASCII encoding, it matches, so the Unicode part of the .NET method is what's the difference.

W6ph5Mm5Pz8GgiULbPgzG37mj9g=

Is there a way in the python script to get an output to match the default .NET version?

+3  A: 

This is the trick:

Encoding.Unicode

“Unicode” encoding is confusing Microsoft-speak for UTF-16LE (specifically, without any BOM). Encode the string to that before hashing and you get the right answer:

>>> import hashlib
>>> p= u'password'
>>> hashlib.sha1(p.encode('utf-16le')).digest().encode('base64')
'6Pl/upEE0epQR5SObftn+s2fW3M=\n'
bobince
Thanks, this is great info. I probably wasn't clear enough, but can this be applied to the already hashed password? If the original password in python wasn't encoded in this way, there' probably no way I'm going to get it backed out to apply the utf-16le encoding. Does that make sense?
RyanW
Indeed, once it's hashed you're never getting it back.
bobince