port sha 1 hash from C# to Android/java

I need to port the following code from C#

    private string hashcode(string code)
    {
        byte[] bytes = Encoding.Unicode.GetBytes(code);
        byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(bytes);
        return Convert.ToBase64String(inArray);
    }

to an Android App. I have this in Java:

private static String hashCode(String userCode) {
    String hashSha1;
    MessageDigest digest = null;
    try {
        digest = MessageDigest.getInstance("SHA-1");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    digest.reset();
    byte[] data = digest.digest(userCode.getBytes());
    return Base64.encodeToString(data, Base64.DEFAULT);
}

Alas, this code does not produce the same results. Finding out why is a pretty wild goose chase.

What can I do in Android to get the same hashes?

Jon Skeet
people
quotationmark

This is the C# code you've got for converting the userCode string to bytes:

byte[] bytes = Encoding.Unicode.GetBytes(code);

And the Java code is just:

userCode.getBytes()

That means in Java you're using the platform-default encoding, is UTF-8 on Android. You should specify the equivalent encoding to Encoding.Unicode, which is StandardCharsets.UTF_16LE.

You should pretty much never call either String(byte[]) or String.getBytes() which both use the platform-default encoding. Always specify the encoding to use.

On a more general point, you said that "finding out why is a pretty wild goose chase" - but in situations like this, the solution is almost always to log in detail one step in the transformation at a time. You have three transformations here:

  • String to byte[] (encoding userCode as binary data)
  • MD5 hashing (byte[] to byte[])
  • Encoding the hash as base64

If you had taken each of those steps individually, and logged the results, you'd have spotted that the problem was in the first step.

people

See more on this question at Stackoverflow