Can Python encode a string to match ASP.NET membership provider's EncodePassword
Question: 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?


Answer: 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'
    

