检查文件内容是否在 C# 中更改的最简单方法是什么? Sha、crc32、md5 还是其他?

What is the simplest way to check if a content of a file was changed in C#? Sha, crc32, md5 or something else?

我想检查一个文件的内容是否改变了。 我的计划是在文件的最后一行添加一个散列。

稍后,我可以读取文件,对其进行哈希处理(对除最后一行以外的所有内容进行哈希处理)并将其与文件的最后一行(初始哈希)进行比较。

我无法使用最后修改的 date/time。我需要使用存储在文件中的散列或任何类型的编码。我使用 C# 编写应用程序代码。 最 reasoneble/easiest 的方法是什么?我不知道以下哪个适合我:Sha1,2,3 - crc16/32/64 - md5?我不需要快速或安全的方法。

谢谢!

你想保护自己免受什么伤害?

意外更改?那么你的方法听起来不错。 (确保在最后一行哈希也被意外删除时添加处理。)

恶意更改?然后你需要散列文件内容加上一些私钥,并使用安全的散列算法。 MD5 非常适合意外更改,因为它速度很快,但从密码学角度来看,它被认为是损坏的。

在我看来,如果将散列存储在文件中,就会遇到先有鸡还是先有蛋的问题。在对文件进行哈希处理之前,您不会知道哈希值。但是当您对文件进行哈希处理并将该值添加到文件末尾时,哈希值将发生变化。很明显,您需要对文件进行哈希处理而不包括实际的哈希值本身。 你已经说过了,但我再次添加它以澄清我接下来的观点。

诀窍在于 hash/sum 算法会为您提供整个文件(或字节流,或其他)的总和。他们不会像以前那样给你一个“运行 总数”。这意味着您需要在测试之前将哈希值与其余内容分开,以查看它是否已更改。除非您自己编写自定义哈希工具。

这当然可以使用所有散列算法,但是你问这个问题的事实让我相信你可能不想写一个麻烦的自定义(例如)SHA256 工具,专门设计用于在到达存储的哈希值时退出。

在我看来,你有三个选择:

  1. 将散列与您的文件分开存储 - 或者至少编写一个不包含散列的临时文件,然后对其进行散列。这将允许您使用已内置到 C# 中的散列工具,而无需任何修改或花哨的技巧。我知道这并不完全符合您列出的要求,但这是您可以考虑的一个选项。

  2. 你没有提到文件的大小,但如果它足够小,你可以简单地将它放入内存减去哈希的字节,哈希你的 in-memory使用 built-in 工具获取数据,然后进行比较。这将再次允许您使用 built-in 工具。

  3. 使用自定义散列工具,该工具在到达“有趣”数据的末尾时会故意退出。如果是这样的话,我毫无疑问会推荐像 CRC 这样的 non-secure 散列方法,仅仅是因为它会更容易理解和自己修改代码(毕竟它是更简单的代码)。您已经提到您不需要它来确保安全,因此这将满足您的要求。

如果您决定使用选项 #3,那么我建议您转到 Rosetta Code 以在 C# 中搜索 CRC 算法。从那里你可以读取你的文件,减去哈希的字节,通过你的哈希算法发送余数。那里列出的算法一次处理所有字节,但将累加器转换为参数以便您可以分块发送数据是微不足道的。这将允许您在原地处理任意大的文件。

[编辑] FWIW,我已经走了类似的路。在我的例子中,我编写了一个自定义工具,它允许我们通过 WAN 增量复制非常大的文件。太大以至于我们无法安全地复制文件。正确使用该工具是远程源服务器,pre-run CRC32 检查并以任意间隔保存总和。然后将 CRC32 校验复制到客户端,并开始复制文件。如果目标在中途停止,或者可能以某种方式损坏,可以简单地提供本地部分的名称、远程源、包含 CRC32 和的文件,最后是目标。该程序将从本地部分开始复制,并且仅在发现部分 CRC32 和问题时才开始从远程复制。我们的问题是字节副本末尾的简单简历并不总是有效。这令人沮丧,因为复制需要很长时间。我和我的队友笑了好几次说我们可以试试U盘和信鸽...