【问题标题】:How can you generate the same MD5 Hashcode in C# and Java?如何在 C# 和 Java 中生成相同的 MD5 哈希码?
【发布时间】:2011-02-24 14:10:32
【问题描述】:

我有一个在 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();

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

MessageDigest m = MessageDigest.getInstance("MD5");
m.update(bytes,0,bytes.length);

String hashcode = new BigInteger(1,m.digest()).toString(16);
return hashcode;

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

有没有办法为相同的字节数组生成相同的 md5 哈希?

按需:

这是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();
}

这是我的 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;
}

干杯

【问题讨论】:

  • 您发布了测试 code 但没有测试 data。不要从文件或通过 HTTP 加载 - 只需将一些数据(任何数据)硬编码到您的测试中。
  • 特别是,我刚刚用我正在寻找的示例编辑了我的答案 - 那些 do 显示相同的哈希,代码实际上是相同的和你一样。请注意,在您的 C# 代码中,您忽略了 Stream.Read 的结果,这绝不是一个好主意...

标签: c# java md5 bytearray


【解决方案1】:

我知道这个话题很老,但我刚才遇到了同样的问题,找不到适合我的答案。我正在为游戏编写补丁程序,需要文件的md5 hashcode 来确保文件是最新的,但是尽管文件相同,但 C# 和 Java 给了我不同的字符串。

我是这样解决的:

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

这将创建一个 32 个字符的十六进制字符串。 Apache Commons DigestUtils.md5Hex(InputStream) 也一样,现在唯一不同的是C#的例子返回的是大写字符串,所以解决方法就是把Java程序中的hash转换成大写字符串。

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

生成的哈希看起来像F674865D8A44695A2443017CFA2B0C67

希望这对某人有所帮助。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

      而不是调用update 然后digest

      绝对确定你在这两种情况下得到相同的数据吗?您能否使用相同的硬编码数据发布示例程序以显示此失败?

      编辑:这是我想到的那种测试。这两个程序给出了相同的结果:

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

      【讨论】:

      • 通过使用它,我能够从 C# 和 C++ 代码中获得相同的哈希值。太棒了!
      【解决方案4】:

      您好,我正在使用此代码,它可以工作

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

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

      【讨论】:

      • 请注意,如果您的字符串不完全由 ASCII 数据构成,您将丢失信息...
      • @estergones:你有 PHP 的等效代码吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-17
      • 2020-12-08
      相关资源
      最近更新 更多