【问题标题】:Chicken/Egg problem: Hash of file (including hash) inside file! Possible?鸡/蛋问题:文件内的文件哈希(包括哈希)!可能的?
【发布时间】:2011-05-24 21:03:40
【问题描述】:

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

我完全理解,从定义上讲,这对于像 md5/sha 这样的单向加密哈希方法来说是不可能的。

我也知道容器存储验证数据的可能性与 zip & co 一样。

我也知道可以单独计算哈希并将其与文件一起发送或将其附加到末尾或客户端在计算哈希时忽略它的地方。

这不是我想要的。

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

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

我真的不是很喜欢数学,但难道不能有一些真正先进的指数模多项式循环反向引用除法的东西来使这成为可能吗?

如果没有,反对它的证据是什么(如果有)?

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

【问题讨论】:

  • 回答上述问题至少和这个问题一样难:Is there an MD5 Fixed Point where md5(x) == x?
  • @Greg:重读。 OP 知道使用 MD5 和 SHA 是不可能的。
  • 它不是那个的副本,因为它处理一个特殊的加密散列并且问题是不同的,因为它需要与自身的功能相同。我的问题是关于更多算法,非密码以及包含该哈希的数据。不是哈希本身。
  • @Jason S:这不是“不可能的”。很难。

标签: algorithm math hash


【解决方案1】:

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

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

(可能有更多细节,但目前不正确。您基本上需要在 Galois 字段中计算 (CRC_desired - CRC_initial) * 2-8*byte_offset,其中 byte_offset 是之间的字节数占位符字节和文件的结尾。)


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

【讨论】:

  • 哇! crc 不是那么难,在考试期间在纸上做过一段时间:D 让我想通过... crc 也是理想的(良好的错误检测),当我想到这个 +1 时,我想到了这一点
  • 问题是 crc32 作为哈希值比 md5 差 79,228,162,514,264,337,593,543,950,336。 32 位校验和很容易发生冲突。
  • 更糟糕的是,我知道这一点。但它仍然是一个非常好的完整性检查器,如果这是唯一的要求的话
  • 这基本上是泰勒的第二个选择;散列数据,然后将散列附加到文件的前面。这样做的缺点是哈希是文件的一部分,这意味着您必须信任文件的一部分以确保您可以信任它的其余部分。它还允许破解一个文件来篡改文件,而不必同时破解文件和 MD5 签名存储库;因此,它只能证明文件的格式正确,而不是文件的合法作者上传的内容。
  • 顺便说一句:如果您使用 SurroundSCM 进行源代码控制,请不要这样做。默认情况下,它使用 CRC-32 作为文件是否已从存储库中的副本更改的指示符,而没有使用 MD5 或 SHA1 的选项。 (!!!)
【解决方案2】:

这当然是可能的,有多种方式。但是,它无法防止故意篡改。

例如,让

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

这里的想法是任何与 0 模 65521 一致的 32 位整数都不会影响 X 的哈希值。然后,由于 65521

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

    • 酷。这就是我需要的。事情是不会有攻击者,文件是通过生产管道处理的,只有文件被传输,我必须在每一步都更新它,以将一个长哈希传递给 ck 以确保完整性。我只是想确保文件没有损坏。
    【解决方案4】:

    不,不可能。你要么是一个单独的哈希文件 ala md5sum,要么嵌入的哈希仅用于文件的“数据”部分。

    【讨论】:

    • 我知道可能有其他情况听起来不合逻辑。但是你有什么证据/理由吗? - 编辑:Jason S 的回答另有建议
    • 哈希需要完整的文件知识,并且包含在文件中。因此,您创建文件,创建不包含散列的文件的散列,然后将散列添加到更改其内容的文件中,因此再次散列文件将产生不同的散列。哈希将用作校验和,以证明文件未被篡改,因此在对文件进行哈希处理(通过添加哈希)后篡改文件,在给定适当的哈希算法的情况下,总是会在接收端重新哈希失败。
    【解决方案5】:

    the nix package manager 这样做的方式是,在计算哈希时,您假装文件中哈希的内容是某个固定值,例如 20 x,而不是文件的哈希,然后您将哈希写入那些 20 x 的,当您检查哈希时,您会读取它并再次忽略它,假装哈希只是 20 x 的固定值在哈希时

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

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

    【讨论】:

    • 是的,这基本上是单独发送哈希但在同一个文件中......我知道这种可能性,但不幸的是不能这样做。我不太相信这是不可能的,看看 Jason S 的说法。对我来说听起来很合乎逻辑。
    • 所以实际上这归结为找到一个固定点H(h||m) = h,至少在正常操作期间这确实不是一个人应该做的事情,但这是堆栈溢出,它根据定义是异常的
    • 完全正确。为此+1,尤其是最后一部分;)
    【解决方案6】:

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

    同样明显,当然有一些微不足道的“哈希”可以做到这一点。例如,奇数位设置为 1 的数据散列为 00,偶数位设置为 11。哈希不会修改 1 位的奇数/偶数,因此当包含哈希时,文件的哈希值相同。

    【讨论】:

    • 是的,我在脑海中做了那个非常确切的例子,并认为是否有可能扩展逻辑以证明其他方式但没有走远:D
    • 有无数的哈希函数可以工作。其中有多少有用是另一回事......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 2013-06-06
    • 1970-01-01
    • 2017-05-29
    • 2014-05-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多