如何有效地生成并验证文件校验和?

如何有效地生成并验证文件校验和?

我希望能够捕获并验证大规模文件集合的校验和,这些文件通常嵌套在复杂的目录层次结构中。

每个文件都需要校验吗?有没有办法利用现有的目录结构,比如只验证文件树中的一个节点,而不一定验证其中的每个文件?

答案1

使用校验和的最有效方法是让计算机完成所有工作。使用文件系统(例如 ZFS),它会在写入数据时对所有数据进行校验(实际上它使用哈希,这比校验和更强),并在每次读取数据时验证它们。当然,缺点是 ZFS 不知道何时删除或覆盖文件是错误,何时是正常操作,但由于 ZFS 对所有内容都使用写时复制语义,因此您可以使用它的快照功能来降低风险。

ZFS 还可以使用您设置的任何冗余自动恢复哈希校验失败的数据,无论是 raid5 式奇偶校验、驱动器镜像还是重复副本(将副本 = N 属性添加到任何 ZFS 文件系统,它将存储您写入的任何数据的 N 个副本)。它还将哈希存储在 Merkle 树中,其中文件的哈希值取决于块的哈希值,目录条目的哈希值取决于其包含的文件和目录的哈希值,文件系统的哈希值取决于根目录的哈希值,等等。

无论最终采用何种解决方案,您都会发现该过程受到磁盘速度的限制,而不是 CPU 速度的限制。

另外,不要忘记考虑磁盘的 BER。毕竟,它们只是旋转生锈的盘子。消费级驱动器的错误率为每读取 10^14 位,就会有 1 位读取错误,也就是说,每读取 11 TB 就会有 1 位错误。如果您有一个 11 TB 的数据集,并且计算了其中每个文件的哈希值,那么您将错误地计算其中一个校验和,并永久损坏数据集中某个文件的一个块。但是,ZFS 知道它写入池中每个磁盘的每个块的哈希值,因此知道哪个块丢失了。然后,它可以使用池中的冗余(奇偶校验、镜像或额外副本)用正确的值重写该块中的数据。当您使用 zfs send 或 accept 将数据从主系统复制到备份时,这些安全功能也适用。

不过,Ben 在评论中提出了一个很好的观点。ZFS 不会向用户公开它计算的任何哈希值,因此进入或离开 ZFS 系统的数据应该带有哈希值。我喜欢 Internet Archive 使用 xml 文件来实现这一点,该文件随档案中的每一项一起提供。请参阅https://ia801605.us.archive.org/13/items/fakebook_the-firehouse-jazz-band-fake-book/fakebook_the-firehouse-jazz-band-fake-book_files.xml举个例子。

答案2

也许这是提出这个问题的好时机袋装。这是一种非常简单但功能强大的文件打包格式,用于存档、长期保存和传输数字对象。用户包括国会图书馆和加州数字图书馆。

BagIt 工具(它们存在于多种编程语言中)将您的文件放入特定的目录结构中,并为您进行校验和/哈希处理。仅此而已。

PS:当然,BagIt 工具还可以根据包含的校验和/哈希值验证包,并且您可以向包中添加一些元数据。但这就是包所能达到的最复杂程度。

答案3

我会为每个文件生成校验和。校验和非常小,而为整个目录生成校验和需要您处理每个文件(至少如果您说的不是目录校验和,而是仅根据目录条目生成的校验和 - 我也会生成它们,以确保没有数据被删除)。

假设您对整个存档都有一个校验和。您知道数据已损坏,但您不知道这是否只是一个文件,更重要的是,不知道是哪个文件。使用单独的校验和可以为您提供更大的灵活性。您可以检测单个损坏的文件,并用其他备份中的文件替换它(反过来,其他文件也可能已损坏)。

这样,您的数据就更有可能保存下来。

答案4

我已经看过答案了,尽管我喜欢依靠 ZFS 来处理数据层错误的想法,但仍然存在文件被更改的问题,无论是错误还是恶意的。在这种情况下,ZFS 不会保护您,并且像其他人提到的那样,它不会为您提供用户可查看的“哈希”以存储在其他地方进行外部验证。

有一款名为 TripWire 的 Linux 应用程序被广泛用于监控系统可执行文件,以验证它们在受到攻击后是否被更改。该项目显然已被放弃,但有一款名为 的新应用程序AIDE (Advanced Intrusion Detection Environment),在 ServerFault 上值得推荐:

https://serverfault.com/questions/62539/tripwire-and-alternatives

安装后,它会每 x 分钟运行一次,用户可配置,它会检查您指定的所有文件夹中的文件是否有更改。它需要运行一次来​​计算所有文件哈希值,然后它会根据当前文件检查所有哈希值,并确保它们仍然相同。您可以指定要使用的哈希类型或哈希组合(我不建议使用比 SHA-256 更弱的哈希值)、要使用的文件属性(内容、大小、修改时间戳等)、检查频率、如何/在何处存储哈希数据库等。

有些人可能认为这有点小题大做,但根据 OP 的要求,他可能会更加安心,因为他存储的数据在一定时间点之后会保持不变。

相关内容