Having trouble mimicing Java MessageDigest output in C#

Viewed 126

I have a java program (third party so can't edit) that is generating a Base64 encoded string from a MD5 hash. It's not being used for security reasons in this instance, more to get a unique value for the string provided for easy comparison later on.

I'm trying to generate the same Base64 string in my C# application so I can also use it for comparison later.

Here's the code and then I'll go into what I've tried.

Relevant parts of the Java program (pulled from the IntelliJ decompiler):

String encodedValue = 
encode("Lot#: 9999  ExpDate: Mar 6, 2020  Date: Apr 1, 2020  QtyD: 0.56  Chk: True  Int: 120  Mon: $90.00");


public static String encode(String password) throws IOException, NoSuchAlgorithmException, MessagingException {

ByteArrayOutputStream out = new ByteArrayOutputStream();

try {
    OutputStream encoder = MimeUtility.encode(out, "base64");
    try {
        byte[] encrypted = encrypt(password);
        encoder.write(encrypted);
        encoder.flush();
        return new String(out.toByteArray());
    catch(...) {}
catch(...){}
}


private static byte[] encrypt(String password) throws NoSuchAlgorithmException {
    MessageDigest algorithm = MessageDigest.getInstance("MD5");
    algorithm.reset();
    algorithm.update(password.getBytes());
    return algorithm.digest();
}

C# section

string input = 
"Lot#: 9999  ExpDate: Mar 6, 2020  Date: Apr 1, 2020  QtyD: 0.56  Chk: True  Int: 120  Mon: $90.00";

using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
    byte[] inputBytes = Encoding.GetEncoding(28591).GetBytes(input); //matches Java so far
    byte[] hashBytes = md5.ComputeHash(inputBytes);
    string base64 = Convert.ToBase64String(hashBytes);
}

If I run both input byte[] (password.getBytes() and Encoding.GetEncoding(28591).GetBytes(input)) through the Base 64 encoder, they both return the same value.

TG90IzogOTk5OSAgRXhwRGF0ZTogTWFyIDYsIDIwMjAgIERhdGU6IEFwciAxLCAyMDIwICBRdHlEOiAwLjU2ICBDaGs6IFRydWUgIEludDogMTIwICBNb246ICQ5MC4wMA==

This leads me to believe the encoding is correct between both of them.

If I inspect the encrypted byte[], the values don't match

Java byte[] value

C# byte[] value

Based on this and this I realized that Java uses signed numbers so the display output on the debugger really isn't going to match, but the actual values still should.

I tried using

for (byte b : bytes) {
    System.out.println(b & 0xFF);
}

to view the signed counterpart in c#, C# signed array but the arrays don't match still.

And for the final output, the base64 encoded strings

Java
0mfvZiQ7tDOnMsP/qH8CLQ==

C#
W2afrKbW3jHPMv7HHnc8nw==

I'm not sure if the MessageDigest is doing something additional in the encryption that I can't see to replicate, or if I'm missing something entirely.

I'm able to debug both sides so if any additional information would be helpful, let me know.

Any help would be greatly appreciated!

0 Answers
Related