【问题标题】:Different MD5 between Java and C#Java和C#之间的不同MD5
【发布时间】:2015-11-08 12:34:08
【问题描述】:

我想比较同一文件中的 MD5 哈希值。该文件通过来自 Android 的 HTTP POST 作为 byte[] 发送,我还计算哈希并从 .NET 服务器接收,在该服务器中我再次计算哈希,然后想要比较它们。

问题是对于同一个文件,我得到不同的哈希值...

Java 代码

FileInputStream fileInputStream = null;

byte[] bFile = new byte[(int) file.length()];

try {

    fileInputStream = new FileInputStream(file);
    fileInputStream.read(bFile);

} catch (Exception e) {
    e.printStackTrace();
}

try {
    MessageDigest md = MessageDigest.getInstance("MD5");

    int read = 0;
    while((read = fileInputStream.read(bFile)) != -1) {
        md.update(bFile, 0, read);
    }
    fileInputStream.close();

    byte[] mdBytes = md.digest();

    StringBuffer sb = new StringBuffer();
    for(int i=0; i < mdBytes.length; ++i) {
        sb.append(Integer.toString((mdBytes[i] & 0xff) + 0x100, 16).substring(1));
    }

    // generated MD5 is d41d8cd98f00b204e9800998ecf8427e


} catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

C#代码

using (var md5 = MD5.Create())
{
    using (var stream = File.OpenRead(filePath))
    {
        string hexString = ToHex(md5.ComputeHash(stream), false);

        // Generated MD5 is d167df114a478809ef71fb7e10c40f8c
    }
}

public string ToHex(byte[] bytes, bool upperCase)
{
    StringBuilder result = new StringBuilder(bytes.Length * 2);

    for (int i = 0; i < bytes.Length; i++)
        result.Append(bytes[i].ToString(upperCase ? "X2" : "x2"));

    return result.ToString();
}

更新

我尝试将 Java 代码更改为

StringBuffer sb = new StringBuffer();
for(int i=0; i < mdBytes.length; ++i) {
    sb.append(String.format("%02x", mdBytes[i]));
}

结果总是一样的......

【问题讨论】:

  • 我认为问题在于对值进行十六进制处理,而不是获取它的 MD5。
  • 也这么想...但无法弄清楚错误在哪里
  • 为什么要使用不同的方式来获取 HEX 中的字符串?我不确定该代码中发生了什么:sb.append(Integer.toString((mdBytes[i] &amp; 0xff) + 0x100, 16).substring(1));
  • 基本上是在网上找到了代码... :( 需要查...
  • 我不是java人,但在.Net流中,阅读FileStream后,您应该回到开头,然后再重新阅读。

标签: java c# hash cryptography md5


【解决方案1】:

首先,通过使用许多免费提供的工具中的一个(或多个)来计算 MD5 哈希并查看您的 C# 或 Java 代码是否正确(也许两者都是错误的,好吧 :-)),将您的工作减半。

那我们拭目以待。

更新:

在 Java 案例中,您将数据读入字节数组;之后您使用相同的流(已经是 EOF),因此永远不会调用 md.update

更新 2:

所以,写

[...]
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bFile, 0 , bFile.length);
byte[] mdBytes = md.digest();
[...]

你的基本没问题。顺便说一句,将字节数组转换为十六进制字符串的有趣技术... :-) 您可能想寻找更好的方法,但...

【讨论】:

  • 我已经从fileformat.info/tool/hash.htm 尝试过,两个文件(服务器和客户端)的哈希值相同......所以绝对是算法错误
  • 哦,有误会。我打算使用外部 MD5 工具来检查您的两个 实现 的结果,并找出至少一个是否有效。不检查文件在传输时是否损坏。更具体地说,检查代码 cmets 中提到的两个 MD5。
  • @Mihai 或者因为他们也使用.Net :) LOL
  • @Stefano 我怀疑任何 java 或 .net 散列算法都有问题。很可能是您的帖子散列操作受到指责。
【解决方案2】:

读取文件流后,您必须回到流的开头才能正确计算散列。

【讨论】:

  • Java 不允许将流嵌套在一起吗?例如,.Net 确实可以,因此人们可以只读取一次文件流,同时通过哈希器将其馈送。它不仅具有性能优势(文件不必被读取两次)并允许处理不可搜索的流(例如网络),而且更灵活且更容易出错。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
  • 2011-03-13
  • 1970-01-01
  • 2013-04-13
  • 1970-01-01
相关资源
最近更新 更多