5

I know very little about encryption/hashing.

I have to hash an encryption key. The example in Java is like this...

String encryptionKey = "test";

    MessageDigest messageDigest = MessageDigest.getInstance("MD5");
    messageDigest.update(encryptionKey.getBytes("UTF-8"), 0, encryptionKey.length());
    byte[] encryptionKeyBytes = messageDigest.digest();

Now correct me if I'm wrong, but the above code hashes the string with the MD5 algorithm.

And I want the same result when I hash the same string in C#.

My current C# code looks like this...

string encryptionKey = "test";

        var md5 = MD5.Create();
        var keyBytes = Encoding.UTF8.GetBytes(encryptionKey);
        byte[] encryptionKeyBytes = md5.ComputeHash(keyBytes);

But the end byte results do not match.

Java gets...

[0] 9   
[1] -113    
[2] 107 
[3] -51 
[4] 70  
[5] 33  
[6] -45 
[7] 115 
[8] -54 
[9] -34 
[10]    78  
[11]    -125    
[12]    38  
[13]    39  
[14]    -76 
[15]    -10 

C# gets...

    [0] 9   byte
    [1] 143 byte
    [2] 107 byte
    [3] 205 byte
    [4] 70  byte
    [5] 33  byte
    [6] 211 byte
    [7] 115 byte
    [8] 202 byte
    [9] 222 byte
    [10]    78  byte
    [11]    131 byte
    [12]    38  byte
    [13]    39  byte
    [14]    180 byte
    [15]    246 byte

I need my C# code to get the same result as the Java code (not the other way around), any ideas?

Thank you.

6
  • 3
    Java's bytes are signed. C# bytes are not. Notice that only the places the Java byte is negative it's wrong. Commented Jun 14, 2012 at 18:19
  • besides the equal result, you have a pretty bad mistake in java code: encryptionKey.getBytes("UTF-8"), 0, encryptionKey.length() I leave it to you to figure what the error is. Last comparing a direct string representation (toString) is always a bad idea Commented Jun 14, 2012 at 18:24
  • @bestsss I'm using a breakpoint to check the values. I think the breakpoint values are produced from the toString representation (might be wrong). How would you go about comparing byte values? Commented Jun 14, 2012 at 18:42
  • unsigned hex is usually the norm for presenting byte[] as you can easily see both nibbles. btw did you find out where the error is? Commented Jun 14, 2012 at 19:43
  • @bestsss It's using the byte[] array for the data, and the length is coming from the string (instead of the byte[]). Is that what you were pointing out? If not, I don't know. That java code is an encryption/decryption demo sent to me. The C# I have to write to produce the same result. Commented Jun 14, 2012 at 20:03

1 Answer 1

12

Actually, the results are identical. Like other integral types, a byte value may be interpreted as either signed or unsigned. For example, 10001111 would correspond to 143 (your second C# value) if interpreted as unsigned. However, if interpreted as signed (using two’s complement), its value would be -113 (your second Java value).

Thus, the disparity seems to be caused by your values being formatted as signed in Java but unsigned in C#. If you want to get signed bytes in C#, you can use:

sbyte[] encryptionKeyBytesSigned = 
    encryptionKeyBytes.Select(b => (sbyte)b).ToArray();

However, be careful that this is not merely a formatting issue that only arises when you display your values. When saved to file, both results should be identical.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your answer... That last statement seems to contradict if I'm reading it correctly. If you save both to file and they are identical, then it IS merely a formatting issue that arises when you display the values. Can you clarify? I am going to take this hashed value (in byte[]) and use it as an encryption key. So if it's merely a displaying issue, I would think it'll be okay without conversion. I don't think the encryption function will take sbyte[] instead of a byte[].
N/m. You were just warning me to check and make sure. I got it.
@Theo: Yes, I assume that it’s a formatting issue and, when saved to file, the resulting files should be identical even without converting the C# values to signed byte. However, to be honest, I’m not that familiar with Java (I can only vouch for your C# code), so I would perform some testing to make sure.
You were right about the formatting issue. When written to file, the both show the same gibberish characters. Thank you for your help.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.