管理数据(第一部分:使用校验和与哈希值实现数据完整性

片场数据管理最重要的目标之一是保持拍摄过程中记录和创建的所有数据的完整性和完全性。由于这是您作为数字影像工程师或数据管理员的责任,因此熟悉一些核心概念是非常有用的。

本文是两部分系列文章中的第一篇,介绍了数据管理技术方面的基本知识。我们将深入探讨数据完整性的含义、可能威胁数据完整性的一些潜在问题,以及校验和与哈希算法如何帮助我们保护数据完整性。

在后续的文章中,我们将讨论清单文件以及如何使用清单文件来保持数据的完全性,从而转向成功数据管理的第二个支柱。但首先,我们还是要谈谈数据完整性!

数据完整性

保持完整性(或 “数据完整性”)是指确保数据在整个生命周期内都是 “正确 “的。对于已录制的媒体文件,这意味着文件未被无意更改,所包含的内容与摄影机录制时相同。

理论上听起来很简单,但实际操作起来却很棘手。试想一下,将文件从摄影机数据卡传输到外置硬盘时,需要一长串硬件和软件组件协同工作: 

  • 通过可插拔电缆连接的各种不同的设备,
  • 读卡器自带控制器和连接器,
  • 固态硬盘或磁盘控制器组件和缓存,
  • USB 或 Thunderbolt 接口组件,
  • RAID 阵列系统(硬件或软件阵列),
  • 多个文件系统(可能是不同类型的),有时是虚拟文件系统(如 Codex VFS),在需要时为磁盘卷创建文件数据,
  • 一个操作系统,带有用于读写文件的文件访问例程、访问权限管理系统、RAM 中的文件缓存机制、多线程支持,
  • 以及执行数据传输的软件应用程序,如 Pomfort Silverstack 或 Offload Manager。

好消息是:文件发生意外更改的情况并不常见。不过,这也并非不可能。物理和交互式组件的数量、物理连接器和电缆连接、独立电源以及不同供应商的固件和软件版本,都会在某些情况下增加出错的几率。那么,潜在的后果是什么呢?让我们来看几个在文件传输或存储过程中可能出现问题的例子: 

空文件: 复制过程中可能会出现这种情况,即文件已创建,但未成功写入其内容。可能的原因 介质已满、访问权限不足或创建文件后进程中止。

文件缩短: 在复制过程中,由于写入过程不完整,可能会出现这种情况。可能的原因:复制中止、介质已满、电源或连接故障以及未恢复进程。

文件内容错误:可能的原因有很多: 这可能发生在数据块在写入过程中出现混乱,例如,多线程的问题或错误。数据块在卷上分配但未写入时也可能发生这种情况。这样,格式化存储卡前写入的旧内容就会 “闪现 “出来,显示为错误的内容。另一种可能的情况是在传输或存储过程中出现比特错误,例如,组件或存储/内存出现故障或不可靠。文件内容也可能完全错误或损坏,例如文件系统结构损坏。

通过编辑修改文件:文件也可能被编辑改变,例如,软件应用程序在打开文件时覆盖了整个文件或部分文件,而用户可能无意中操作或者未察觉到这种操作。

如何实现数据完整性 

好了,恐怖场景就讲到这里。您现在可能会问自己,该如何帮助维护数据完整性。下面,我们将向你介绍一个有助于检测上述问题的核心概念: 计算和验证单个文件的校验和。

首先,让我们来了解一下什么是校验和、如何使用哈希算法来创建校验和,以及如何使用它们来检查文件内容的完整性。

为了检测文件在传输或存储过程中的错误,通常会创建校验和。其原理是使用一种算法(校验和函数),从任意大小的数据块(例如,文件)中创建一小段数据(校验和)。一个好的校验和函数有一个非常(非常非常)高的概率,即当文件内容的任何部分发生变化时,给定文件的校验和会变得不一样。校验和函数也是确定的,因此可以随时重新计算校验和。

换句话说:

在传输或复制文件后,计算文件的校验和,将计算出的校验和与之前为该文件计算出的校验和(如在源硬盘卷上)进行比较,就能以非常(非常非常)高的概率确保文件内容保持不变。如果校验和不相等,则可以肯定内容发生了变化。如果校验和相等,则可以认为文件未被修改。

这是在软件中使用校验和来检测文件更改,和实施的所有文件的完整性检查的基本原理。

校验和方法种类繁多,有些适用于很小的数据块,有些甚至用于纠错。但最适合和最常用的,确保文件数据完整性的校验和函数是hash(哈希)算法。

HASH (哈希)算法

hash(哈希)函数将任意大小的数据块(即文件内容)映射为一个短的(固定的)大小值。这正是我们对校验和函数的要求。hash 函数创建的值称为 “哈希值”。用于创建哈希值的哈希算法名称有时也称为 “哈希类型”(例如,一个文件的哈希值可能是 MD5 类型的 f5b96775f6c2d310d585bfa0d2ff633c)。

根据维基百科,”一个好的哈希函数要满足两个基本特性: 1) 计算速度要非常快;2) 尽量减少输出值的重复(碰撞)”。

当两个不同的数据文件产生相同的哈希值时,就会发生 “碰撞”。 发生这种情况的概率应尽可能小。相反,输出范围内的每个哈希值都应以大致相同的概率生成。这样,哈希算法就能很好地实现我们的目的 – 当给定的数据不同时,它就会产生不同的哈希值。

以下是媒体管理流程中通常使用的哈希算法的几个示例,并附有示例值:

  • MD5 (128 bit, 示例值: f5b96775f6c2d310d585bfa0d2ff633c)
  • xxhash64 (64 bit, 示例值: f409b64875d02fa1)
  • C4 (512 bit, 示例值: c45TH1egbyWxtjgFmisoPypYXcizxPbywFzkbhevak2NgQr3HND5j99HR8UQDwT8pQoS8k3yxhLRGJPoNgR1zUin31)

碰撞概率

让我们考虑一种能产生完全均匀分布值的哈希算法。那么,当两次查看一个文件时发生碰撞的几率(即修改后的文件会产生相同的哈希值)可以由哈希值的长度决定,如下所示:

碰撞概率(即理想的哈希算法对两个不同文件内容产生相同哈希值的概率)为 其中,l 是哈希长度(比特)。

因此,对于哈希值长度为 64 位的哈希算法(例如 xxhash64),该概率为 1 / 2^ 64,约为 1/18.446.744.073.709.551.616 或 5.42101086 × 10^ -20。换句话说,您需要尝试对同一文件进行约 185.395.973.344.368.338(185 quadrillion)次随机更改,直到所有比较的总体碰撞概率超过 1%。也就是说,每秒尝试 1000 次给定文件的更改,需要 5.878.867(590 万)年的时间,而 99% 的概率仍不会发生碰撞。

对数学感兴趣的朋友请看 上述示例的计算公式:一个文件中必要的随机更改次数,以便超过理想的 64 位哈希算法 1%的碰撞概率

即使哈希算法并不能完全均匀地分配值,但可以想象,64 位对于哈希值来说已经是很好的大小了,可以检测文件中的任意变化。

速度

哈希算法可能成为数据传输时的限制因素,因为我们总是希望在传输过程中创建哈希值。因此,除了传输实际数据外,还需要计算这些数据的哈希值 – 这当然需要额外的 CPU 时间。xxhash 系列哈希算法的网站提供了不同哈希算法的速度概览。

来自 https://cyan4973.github.io/xxHash/ 的不同哈希算法的基准测试,为简化起见进行了调整

第一个启示是,长度(即哈希值的位数)并不一定与算法的速度相对应。另一个启示是,最大速度的差异可能很大(例如,在相同的计算机硬件上,XXH3 和 MD5 之间的差异可达约 50 倍)。这是因为哈希值需要一个字节一个字节地按顺序计算,不容易实现多线程。这意味着,一个 CPU 内核的速度限制了哈希值的计算过程,而将一个哈希值计算过程切换到具有更多内核的 CPU 不会使哈希值计算更快(当然,您的软件可能会同时对多个文件进行独立哈希以提高整体吞吐量)。

结论与展望

在本文中,我们讨论了创建校验和将如何有助于检测数据的完整性的问题。我们讨论了哈希算法的使用和哈希值作为校验和的使用,并展示了软件应用程序是如何发现数据在其生命周期内是否发生了变化,并向用户发出相应的警告。

在接下来的文章中,我们将探讨完全性的问题,以及在数据管理流程中采取哪些措施来确保没有文件被遗忘。敬请关注本系列文章的第二部分!

About the Author
Patrick是Pomfort现场应用程序的产品经理。通过在Pomfort的工作,他将软件工程的技术背景与数字电影制作的实践经验相结合 - 并且偏爱创造能应用到实际工作中的软件。