问题 鸡/蛋问题:文件内的文件哈希(包括哈希)!可能?


事情是我有一个文件,有元数据的空间。我想在其中存储用于完整性验证的哈希。问题是,一旦我存储了哈希,文件和哈希就会随之改变。

我完全理解,根据定义,使用md5 / sha等单向加密哈希方法是不可能的。

我也知道容器可以将验证数据与zip内容分开存储。

我也知道可以单独计算散列并将其与文件一起发送,或者将其附加到末尾或客户端在计算散列时忽略它。

这不是我想要的。

我想知道是否有一种算法可以从数据中获取结果哈希,其中包含哈希本身的结果。

它不需要加密或满足很多标准。它也可以基于一些启发式算法,在实际的时间量之后提供所需的结果。

我真的不是很喜欢数学,但是不可能有一些真正先进的指数模多项式循环反向参考偏差使这成为可能吗?

如果没有,最新的(如果有)证据反对它?

我需要tis的原因是因为我希望(最终)与MP4文件一起存储哈希。它的复杂,但其他解决方案并不容易实现,因为文件走过了一个设计糟糕的生产线......


3512
2017-12-13 19:27


起源

回答上述问题至少与此问题一样难: 是否存在MD5固定点,其中md5(x)== x? - Greg Hewgill
@Greg:重读。 OP意识到MD5和SHA不可能实现这一点。 - Jason S
它不是重复的,因为它处理一个特殊的加密哈希,问题是不同的,因为它需要与自身的功能相同。我的问题是关于更多算法,也包括非加密算法以及包含该哈希的数据。不是哈希本身。 - The Surrican
@Jason S:这不是“不可能的”。这个很难(硬。 - Greg Hewgill


答案:


在某种程度上,可以使用CRC执行此操作。我过去所做的是在文件中留出4个字节作为CRC32的占位符,用零填充它们。然后我计算文件的CRC。

然后,通过计算CRC多项式的伽罗瓦域中的数字,可以填充占位符字节以使文件的CRC等于任意固定常数。

(进一步的细节可能但不是正确的。你基本上需要计算(CRC_desired - CRC_initial)* 2-8 * byte_offset字节 在Galois字段中,byte_offset是占位符字节和文件末尾之间的字节数。)


注意:根据@ KeithS的评论,这个解决方案不是为了防止故意篡改。我们在一个项目中使用它作为将嵌入式系统中的元数据绑定到用于编程的可执行文件的手段 - 嵌入式系统本身并不直接了解用于编程的文件,因此无法计算CRC或散列本身 - 用于检测嵌入式系统与用于对其进行编程的文件之间的无意不匹配。 (在后来的系统中,我刚刚使用过UUID。)


7
2017-12-13 19:31



哇! crc并不是那么难,在考试期间不久就在纸上做了:D让我认为通过... crc也是理想的(良好的错误检测)并且在考虑这个时我想到了这个+1 - The Surrican
问题是crc32比作为哈希的md5差79,228,162,514,264,337,593,543,950,336。 32位校验和很容易发生冲突。 - Tyler Eaves
更糟糕的是,我知道这一点。但它仍然是一个非常好的完整性检查器,如果这是唯一的要求 - The Surrican
这基本上是泰勒的第二选择;对数据进行哈希处理,然后将哈希值粘贴到文件的前面。这样做的缺点是散列是文件的一部分,这意味着您必须信任文件的一部分,以确保您可以信任其余部分。它还允许破解一个文件以篡改文件,而不必破解文件和MD5签名存储库;因此,它只能证明文件的格式良好,而不是文件的合法作者上传的内容。 - KeithS
是的!这是唯一的目的...... - The Surrican


当然,这在很多方面都是可能的。然而, 它无法防止故意篡改。

例如,让我们

hash(X) = sum of all 32-bit (non-overlapping) blocks of X modulo 65521. 

Z = X followed by the 32-bit unsigned integer (hash(X) * 65521)

然后

hash(Z) == hash(X) == last 32-bits of Z

这里的想法是任何32位整数与0模数65521一致将对X的散列没有影响。然后,由于65521 <2 ^ 16,散列的范围小于2 ^ 16,并且至少有2 ^ 16值小于2 ^ 32一致到0模65521.因此我们可以将哈希编码为不会影响哈希的32位整数。你实际上可以使用任何小于2 ^ 16的数字,65521恰好是最大的这样的素数。


2
2017-12-13 23:14





不,不可能。您要么是散列ala md5sum的单独文件,要么嵌入式散列仅用于文件的“数据”部分。


1
2017-12-13 19:29



我知道可能有其他情况听起来不合逻辑。但你有任何证据/理由吗? - 编辑:Jason S的回答表明不然 - The Surrican
哈希需要完整的文件知识,并包含在文件中。因此,您创建文件,创建不包含散列的文件的散列,然后将散列添加到更改其内容的文件中,从而再次散列文件将产生不同的散列。散列将用作校验和来证明文件没有被篡改,因此在散列之后对文件进行篡改(通过添加散列)将总是在给定适当的散列算法的情况下在接收端上重新散列。 - KeithS


我记得一个旧的DOS程序能够在文本文件中嵌入该文件的CRC值。但是,这只能通过简单的散列函数实现。
理论上你可以为任何类型的哈希函数创建这样的文件(给定足够的时间或正确的算法),攻击者将能够使用完全相同的方法。更重要的是,他会选择:准确地使用你的方法来获取这样的文件,或者只是为了摆脱支票。

这意味着现在你有两个问题而不是一个问题,两者都应该以相同的复杂性实现。由你来决定它是否值得。

编辑:您可以考虑散列一些中间结果(如RAW解码输出,或特定于您的编解码器的东西)。通过这种方式,解码器无论如何都会拥有它,但对于另一个程序,计算起来会更困难。


1
2017-12-13 20:38



凉。多数民众赞成我需要的。事情是不会有攻击者,文件是通过生产管道处理的,只有文件被转移,我必须在每一步都更新它以传递一个长哈希到完整性。我只想确保文件不会被损坏。 - The Surrican


方式 nix包管理器 这是在计算哈希时,你假装文件中的哈希内容是一些固定值,如20 x而不是文件的哈希,然后你在那些20上写哈希 x当你检查哈希时,你会读到它并再次忽略它假装哈希只是固定值20 x在散列的时候

他们这样做是因为安装包的路径取决于整个包的散列,因此散列具有固定长度,他们将其设置为某个固定值,然后将其替换为真实散列,并在验证时忽略该值他们放置并假装它是固定价值

但如果你不使用这种方法是不可能的


0
2017-12-13 19:36



是的,那基本上是单独发送哈希,但在同一个文件中...我知道这种可能性,但不幸的是不能这样做。我不是真的相信它是不可能的,看看Jason S说的话。听起来很合乎逻辑。 - The Surrican
所以这真的归结为找到一个修复点 H(h||m) = h 这至少在正常操作期间不应该做什么,但这是堆栈溢出,根据定义是异常的 - Dan D.
究竟。为此+1,特别是最后一部分;) - The Surrican


这取决于你对“哈希”的定义。正如你所说的那样,显然有任何伪随机哈希这是不可能的(在合理的时间内)。

同样显而易见的是,当然还有琐碎的“哈希”,你可以做到这一点。例如,具有奇数个位的数据被设置为1到0的散列,并且偶数个1的散列到11。散列不会修改1位的奇数/偶数,因此当包含散列时,文件会对其进行散列。


0
2017-12-13 19:35



是的,我在脑海里做了那个非常确切的例子,并且考虑是否有可能将逻辑扩展到其他方面的证据但是没有达到远:D - The Surrican
有无数个哈希函数可以使用。其中有多少是有用的另一个问题...... - patros