C# MD5 哈希在超过 2GB 的文件上不一致

时间:2021-07-04 09:09:23

标签: c# google-drive-api md5 large-files

我正在编写一个 c# 应用程序来使用他们的 V3 API 下载 Google Drive 文件,并检查 Google 提供的 MD5 哈希以确认下载。一切顺利,应用程序运行正常,除了我在文件大小超过 2GB 时检查 MD5 哈希的失败率超过 75%。一些有效,大多数无效。

如果我使用第 3 方 MD5 实用程序进行检查,它会提供正确的哈希值(与 Google Drive 相同)。我试过单独下载我的应用程序(即通过浏览器),以防万一我的应用程序在下载时做一些奇怪的事情,但在通过我的应用程序检查 md5 哈希时也会失败。所以这显然是我最后发生的事情。

我正在使用 c# System.Security.MD5 库,使用 TransformBlock 和 TransformFinalBlock。我尝试了不同的缓冲区大小,只是为了好玩,但没有运气。我也尝试过完整文件 - ComputeHash(Stream) - 但也失败了。

我唯一能看到的(作为一个完整的吸管)是 inputOffset 和 inputCount 参数是 int,如果这些函数有一个内部“总文件size" 或类似的,它也是一个 int(32 位有符号 - 假设)。

我注意到的另一件事是该进程将每 8-25% 暂停一次,在它继续之前的几分钟内没有任何 CPU、磁盘、RAM、垃圾收集或其他活动。当它“运行”时,我看到磁盘、CPU 等,正如预期的那样,并且进展相当快。这个暂停似乎不会影响最终的哈希是否“成功”,但可能是相关的(我在 2GB 以下的大型文件上也看到了这一点)。

有谁知道这是一个问题吗?我见过几个人就大文件散列问题提出类似问题,但没有帮助的答案是散列应该总是相同的......是的,他们应该,但似乎他们可能不是。最奇怪的是偶尔对大文件进行哈希处理。

下面是代码的简化(错误检查、进度报告等,为了快速阅读而去掉了——是的,我也试过这个简化的代码——同样的问题)。不是最干净的,但它可以工作(除了> 2GB 的文件)。预先感谢您提供有关该问题的任何建议或知识。

            int buffersize = 65536;
            using (var md5 = MD5.Create())
            {
                using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read, buffersize))
                {
                    var block = new byte[buffersize];
                    int length = 0;
                    Int64 filesize = stream.Length;
                    Int64 bytesread = 0;
                    length = stream.Read(block, 0, buffersize);
                    bytesread += length;
                    while (length == block.Length)
                    {
                        md5.TransformBlock(block, 0, length, null, 0);
                        length = stream.Read(block, 0, buffersize);
                        bytesread += length;
                    }
                    md5.TransformFinalBlock(block, 0, length);
                    bytesread += length;
                }
                var hash = md5.Hash;
                return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();

1 个答案:

答案 0 :(得分:0)

不知什么原因,它现在可以工作了。尽我所能猜测(这完全是理论上的,不应该发生),我正在研究应用程序的其他部分,这改变了某些东西的位置以避免出现任何错误......

由于未知原因,它仍然在这里和那里暂停,但哈希现在正确返回(匹配时应该匹配,不匹配时不应该匹配)。