【问题标题】:Why does SHA256 hash not match after uploading and downloading file?为什么上传和下载文件后 SHA256 哈希不匹配?
【发布时间】:2020-02-26 07:50:13
【问题描述】:

我正在为应用程序创建一项功能,以在网络服务器上存储文件,同时在 SQL Server 上维护有关文件的数据。我生成一个 SHA256 哈希并将其存储为 BINARY(32),然后使用 HTTPClient 将文件上传到 WebDav 服务器。稍后,当我想在应用程序中查看文件时,我执行 GET 请求,下载文件,并使用存储的哈希检查 SHA256 哈希。它不匹配:(为什么?

我已经尝试检查服务器和本地机器上的哈希,但它也不匹配。我已经进行了大量研究,并确保我没有对文件名进行哈希处理(您可以查看下面的代码)。

public static byte[] GetSHA256(string path) {
    using (var stream = File.OpenRead(path)) {
        using (var sha256 = SHA256.Create()) {
            return sha256.ComputeHash(stream);
        }
   }
}

上传文件:

public async Task<bool> Upload(string path, string name) {
    var storedHash = GetSHA256(path/name);
    //Store this hash in a database, omitted for brevity
    using (var file = File.OpenRead(path)) {
        var content = new MultipartFormDataContent();
        content.Headers.ContentType.Media = "multipart/form-data";
        content.Add(new StreamContent(file));
        var result = await HttpClient.PutAsync(uri, content);
  }
}

下载:

var result = await HttpClient.GetAsync(uri);
using (var stream = await result.Content.ReadAsStreamAsync()) {
    var fileInfo = new FileInfo("TestFile");
    using(var fileStream = fileInfo.Open(FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Delete)) {
        await stream.CopyToAsync(fileStream);
    }
}
var downloadedFileHash = GetSHA256("TestFile");

//check if downloadedFileHash matches the storedHash by comparing byte[] length and content with for loop.

我希望哈希值会匹配。我知道我遗漏了一些 using 语句和其他代码,但为简洁起见,我省略了一堆。

编辑:下载文件的哈希值保持不变,因此问题不是下载而是上传。我多次上传了相同的文件,但每个文件都取回了不同的哈希值。但不同的哈希值保持不变。

【问题讨论】:

  • 如果您检查字节大小等基本内容怎么办?例如上传/下载?这可能意味着您的 WebDAV 服务器以某种方式操纵该文件。
  • 这个问题不太可能与 SHA256 有任何关系。如果您声称相同的文件/字节数组在不同的机器上产生不同的 SHA256 哈希值,或者代码在上传/下载时损坏文件,您能否澄清一下?
  • 先不上传/下载试试看是否匹配。你有任何例外。如果哈希无效,您应该得到一个异常。所以我的猜测是你正在生成一个新的哈希而不是使用旧的哈希。错误的哈希值会引发异常。

标签: c# .net dotnet-httpclient sha256 webdav


【解决方案1】:

对不起,你们可以删除这个问题,因为我找到了问题/答案,但仍然很困惑为什么会发生这种情况。

原来 webdav 出于某种原因在我的文件中添加了额外的标题,请参阅:Header info being written into file when PUT-ing to a Webdav server

最奇怪的事情。所以我遇到了这个帖子。 https://blogs.msdn.microsoft.com/robert_mcmurray/2011/10/18/sending-webdav-requests-in-net-revisited/

将我的代码改写为

public static async Task<HttpResponseMessage> Upload(string path, string name, FileStream file) {
    var method = new HttpMethod(@"PUT");
    var message = new HttpRequestMessage(method, path/name) {
        Content = new StreamContent(file)
    };

    return await HttpClient.SendAsync(message);
}

而且它有效...但我想知道这两种上传方法有何不同。

【讨论】:

  • 很高兴听到您自己找到了答案。 Stack Overflow 不会因此而惩罚您,因此您应该考虑编辑您的答案,以便帮助最终遇到相同问题的其他人。
猜你喜欢
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-11
  • 1970-01-01
  • 2017-06-04
  • 2019-12-08
  • 1970-01-01
相关资源
最近更新 更多