How can you generate the same MD5 Hashcode in C# and Java?

27,043

Solution 1

That should be fine - although you could make the Java code simpler by just calling

byte[] digest = m.digest(bytes);

instead of calling update then digest.

Are you absolutely sure you've got the same data in both cases? Could you post sample programs showing this failing with the same hard-coded data?

EDIT: Here's the sort of test I was thinking of. These two programs give the same result:

C#:

using System;
using System.Security.Cryptography;
using System.Text;

class Test
{
    static void Main()
    {
        byte[] bytes = { 0x35, 0x24, 0x76, 0x12 };
        MD5 md5 = new MD5CryptoServiceProvider();
        byte[] result = md5.ComputeHash(bytes);
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < result.Length; i++)
        {
            sb.Append(result[i].ToString("x2"));
        }
        Console.WriteLine(sb);
    }
}

Java:

import java.math.BigInteger;
import java.security.MessageDigest;

public class Test
{
    public static void main(String[] args) throws Exception
    {
        byte[] bytes = { 0x35, 0x24, 0x76, 0x12 };
        MessageDigest m = MessageDigest.getInstance("MD5");
        byte[] digest = m.digest(bytes);
        String hash = new BigInteger(1, digest).toString(16);
        System.out.println(hash);
    }
}

Solution 2

Hi I m using this code and it works

C# code :

    public static string ConvertStringToMD5(string ClearText)
{

    byte[] ByteData = Encoding.ASCII.GetBytes(ClearText);
    //MD5 creating MD5 object.
    MD5 oMd5 = MD5.Create();
    //Hash değerini hesaplayalım.
    byte[] HashData = oMd5.ComputeHash(ByteData);

    //convert byte array to hex format
    StringBuilder oSb = new StringBuilder();

    for (int x = 0; x < HashData.Length; x++)
    {
        //hexadecimal string value
        oSb.Append(HashData[x].ToString("x2"));
    }

and Java code :

    private String getMD5Digest(byte[] buffer) {
    String resultHash = null;
    try {
        MessageDigest md5 = MessageDigest.getInstance("MD5");

        byte[] result = new byte[md5.getDigestLength()];
        md5.reset();
        md5.update(buffer);
        result = md5.digest();

        StringBuffer buf = new StringBuffer(result.length * 2);

        for (int i = 0; i < result.length; i++) {
            int intVal = result[i] & 0xff;
            if (intVal < 0x10) {
                buf.append("0");
            }
            buf.append(Integer.toHexString(intVal));
        }

        resultHash = buf.toString();
    } catch (NoSuchAlgorithmException e) {
    }
    return resultHash;
}

Solution 3

I came cross the similar issue that we were using Java MD5 Hash to determine whether a file has been processed. We found we cannot create same hash using .NET library. I tried all above suggestion, unfortunately it is not working for me.

The solution I found out later is: instead of create similar function in .NET, we call Java function directly in .NET. There is one great open source project called Ja.NET. Basically what i did is: create a Java class that create hash using the same code. compile it using Ja.NET javac. Then using bam compile the generated Java class file into DLL and use it in my .NET project.

Solution 4

I know this topic is old but I ran into the same issue just now and couldn't find an answer that worked for me. I was writing a patcher for a game and needed the md5 hashcode of files as a way to ensure that the files are up to date, but C# and Java gave me different strings although the files were identical.

Here's how I solved it:

C# Code:

public static string getMD5(string fullPath)
{
    MD5 md5 = MD5.Create();
    using (FileStream stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        byte[] hash = md5.ComputeHash(stream);
        StringBuilder sb = new StringBuilder();
        for (int j = 0; j < hash.Length; j++)
        {
            sb.Append(hash[j].ToString("X2"));
        }
        return sb.ToString();
    }
}

This creates a 32 character hex string. Apache Commons DigestUtils.md5Hex(InputStream) does the same, now the only different is that the C# example returns an uppercase string, so the solution is simply to convert the hash from the Java program to an uppercase string.

Java code:

public static String checkSumApacheCommons(String filePath)
{
    String checksum = null;
    try 
    {  
         checksum = DigestUtils.md5Hex(new FileInputStream(filePath));
    }
    catch (IOException ex) 
    {
        ex.printStackTrace(System.out);
    }
    return checksum.toUpperCase();
}

The produced hashes look like F674865D8A44695A2443017CFA2B0C67.

Hope this helps someone.

Share:
27,043
user29964
Author by

user29964

Updated on January 26, 2020

Comments

  • user29964
    user29964 over 4 years

    I have a function that generates a MD5 hash in C# like this:

    MD5 md5 = new MD5CryptoServiceProvider();
    byte[] result = md5.ComputeHash(data);
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < result.Length; i++)
    {
        sb.Append(result[i].ToString("X2"));
    }
    return sb.ToString();
    

    In java my function looks like this:

    MessageDigest m = MessageDigest.getInstance("MD5");
    m.update(bytes,0,bytes.length);
    
    String hashcode = new BigInteger(1,m.digest()).toString(16);
    return hashcode;
    

    While the C# code generates: "02945C9171FBFEF0296D22B0607D522D" the java codes generates: "5a700e63fa29a8eae77ebe0443d59239".

    Is there a way to generate the same md5 hash for the same bytearray?

    On demand:

    This is the testcode in java:

    File file = new File(System.getProperty("user.dir") + "/HashCodeTest.flv");
    byte[] bytes = null;
    try {
        bytes = FileUtils.getBytesFromFile(file);
    } catch (IOException e) {
        fail();
    }
    try {
        generatedHashCode = HashCode.generate(bytes);
    } catch (NoSuchAlgorithmException e) {
        fail();
    }
    

    and this is my code in C#

    var blob = GetBlobByHttpPostedFile(httpPostedFile);
    var hashCode = Md5Factory.ConvertByteArray(blob);
    
    private static byte[] GetBlobByHttpPostedFile(HttpPostedFile httpPostedFile)
    {
        var contentLength = httpPostedFile.ContentLength; 
        var result = new byte[contentLength];
        var inputStream = httpPostedFile.InputStream;
        inputStream.Read(result, 0, contentLength);
    
        return result;
    }
    

    Cheers

  • Jon Skeet
    Jon Skeet about 14 years
    Note that if your string isn't entirely formed of ASCII data, you will be losing information...
  • julie
    julie over 6 years
    @estergones: Do you have its equivalent code for PHP?
  • Fabricio
    Fabricio over 6 years
    By using this I was able to get same hash from C# and C++ code. Excellent!