如何在C#和Java中生成相同的MD5 Hashcode?

时间:2022-10-28 17:34:00

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

我有一个在C#中生成MD5哈希的函数,如下所示:

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:

在java中,我的函数如下所示:

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".

当C#代码生成:“02945C9171FBFEF0296D22B0607D522D”时,java代码生成:“5a700e63fa29a8eae77ebe0443d59239”。

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

有没有办法为同一个bytearray生成相同的md5哈希?

On demand:

一经请求:

This is the testcode in java:

这是java中的testcode:

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#

这是我在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

干杯

4 个解决方案

#1


22  

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

这应该没问题 - 尽管你可以通过调用来简化Java代码

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#:

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:

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);
    }
}

#2


4  

Hi I m using this code and it works

嗨,我使用此代码,它的工作原理

C# code :

C#代码:

    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 :

和Java代码:

    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;
}

#3


2  

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.

我遇到了类似的问题,我们使用Java MD5 Hash来确定文件是否已被处理。我们发现我们无法使用.NET库创建相同的哈希。我尝试了以上所有建议,遗憾的是它不适合我。

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.

我后来发现的解决方案是:我们不是在.NET中创建类似的函数,而是直接在.NET中调用Java函数。有一个很棒的开源项目叫Ja.NET。基本上我所做的是:创建一个使用相同代码创建哈希的Java类。使用Ja.NET javac编译它。然后使用bam将生成的Java类文件编译成DLL并在我的.NET项目中使用它。

#4


1  

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.

我知道这个话题已经过时了,但我刚才遇到了同样的问题,找不到适合我的答案。我正在为游戏编写一个修补程序,并且需要文件的md5哈希码作为确保文件是最新的方式,但是C#和Java给了我不同的字符串,尽管文件是相同的。

Here's how I solved it:

这是我解决它的方式:

C# Code:

C#代码:

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.

这将创建一个32个字符的十六进制字Apache Commons DigestUtils.md5Hex(InputStream)执行相同的操作,现在唯一的不同是C#示例返回一个大写字符串,因此解决方案只是将Java程序中的哈希转换为大写字符串。

Java code:

Java代码:

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.

生产的哈希看起来像F674865D8A44695A2443017CFA2B0C67。

Hope this helps someone.

希望这有助于某人。

#1


22  

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

这应该没问题 - 尽管你可以通过调用来简化Java代码

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#:

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:

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);
    }
}

#2


4  

Hi I m using this code and it works

嗨,我使用此代码,它的工作原理

C# code :

C#代码:

    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 :

和Java代码:

    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;
}

#3


2  

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.

我遇到了类似的问题,我们使用Java MD5 Hash来确定文件是否已被处理。我们发现我们无法使用.NET库创建相同的哈希。我尝试了以上所有建议,遗憾的是它不适合我。

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.

我后来发现的解决方案是:我们不是在.NET中创建类似的函数,而是直接在.NET中调用Java函数。有一个很棒的开源项目叫Ja.NET。基本上我所做的是:创建一个使用相同代码创建哈希的Java类。使用Ja.NET javac编译它。然后使用bam将生成的Java类文件编译成DLL并在我的.NET项目中使用它。

#4


1  

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.

我知道这个话题已经过时了,但我刚才遇到了同样的问题,找不到适合我的答案。我正在为游戏编写一个修补程序,并且需要文件的md5哈希码作为确保文件是最新的方式,但是C#和Java给了我不同的字符串,尽管文件是相同的。

Here's how I solved it:

这是我解决它的方式:

C# Code:

C#代码:

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.

这将创建一个32个字符的十六进制字Apache Commons DigestUtils.md5Hex(InputStream)执行相同的操作,现在唯一的不同是C#示例返回一个大写字符串,因此解决方案只是将Java程序中的哈希转换为大写字符串。

Java code:

Java代码:

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.

生产的哈希看起来像F674865D8A44695A2443017CFA2B0C67。

Hope this helps someone.

希望这有助于某人。