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

Aar*_*ein 13 security file-management validation

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

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

小智 14

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

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

不管你最终得到什么解决方案,你总会发现这个过程受到磁盘速度的限制,而不是你的 CPU 速度。

另外,不要忘记考虑磁盘的 BER。毕竟,它们只是旋转的锈板。消费级驱动器每读取 10^14 位的错误率为 1 位错误读取位,这相当于您读取的每 11 TB 中的 1 位。如果您有一个 11 TB 的数据集并计算其中每个文件的哈希值,您将错误地计算其中一个校验和并永久损坏数据集中文件之一的一个块。但是,ZFS 知道它写入池中每个磁盘的每个块的哈希值,因此知道哪个块丢失了。然后它可以使用池中的冗余(奇偶校验、镜像或额外副本)以正确的值重写该块中的数据。

然而,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为例。

  • 即使您运行像 ZFS 这样的文件系统(Btrfs 也有类似的功能,但仍处于大量开发阶段,目前尚未准备好用于生产),您也需要执行定期“清理”操作以确保数据是读取并验证校验和或哈希值。仅计算校验和然后不使用它们直到您*需要*访问数据可能比毫无价值更糟糕。 (3认同)
  • ZFS 计算块的校验和,而不是文件或比特流,不是吗?虽然 ZFS 解决了计算问题,但它似乎不太容易被人工审计,并且不会产生可移植的固定数据,而不管文件系统如何——这是归档所必需的。 (3认同)

Dan*_*lor 6

我会为每个文件生成校验和。校验和非常小,并且为整个目录生成校验和还需要您处理每个文件(至少如果您不是在谈论目录校验和,仅由目录条目构成 - 我也会制作它们,以确保没有数据被删除)。

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

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


Chr*_*sch 5

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

BagIt 工具(它们存在于多种编程语言中)将您的文件放入某个目录结构并为您进行校验和/散列。就这些。

PS:当然,BagIt 工具也可以根据包含的校验和/哈希验证包,您可以向包添加一些元数据。但这和袋子一样复杂。