【问题标题】:How to combine sha hashes?如何组合sha哈希?
【发布时间】:2020-02-17 17:17:38
【问题描述】:

我已经订购了数据块,每个数据都使用 sha256 单独散列。我想将这些哈希组合成一个 sha256 哈希。我应该只是将哈希作为数据输入 sha256,还是从数学/加密的角度来看是否有另一种更好的方法?这似乎是一个微不足道的问题,但当涉及到加密时,直觉往往是错误的。

edit:这样做的目的是形成一种区块链,尽管如今这个术语已经相当多。这是出于完整性目的,而不是工作证明。这个想法是在追随者节点上散列块,在集群领导者上将散列组合成一个散列,以获得一个代表整个链的散列,然后将其添加到要散列的新块中。

有点奇怪,因为它是一个分布式系统,所以“全链哈希”通常有点陈旧,所以我知道在该节点创建块时,该节点所知道的代表链的哈希是什么,但是可能有几个块在该特定哈希处“挂钩到链上”,然后将这些块排序并组合到系统哈希中,最终添加到新块之前。

如果这很重要,我正在使用 Go。

【问题讨论】:

  • 问题是:做什么?
  • 换句话说:您是否想要组合哈希只是因为您想要组合这些,或者是否存在需要这种组合的特定用例。您应该做什么取决于您的特定(和未知)用例。尤其是当您询问如何以正确的加密方式处理它时,有关用例的详细信息是必不可少的。

标签: go cryptography


【解决方案1】:

如果您尝试重新创建已拆分为块(例如 10MB 大小)的大型有效负载(例如 1GB 文件)的哈希,则需要在整个收藏。因此,使用此示例,您无法添加 100 个分块散列来重新创建原始文件的散列。不过……

每个块可以发送 2 个值:

  • 单个块的哈希(就像您现在所做的那样)
  • 中间散列状态,因为您的服务会扫描文件以创建每个块负载:在块的开头和结尾

随着块的流入,可以验证块N末尾的哈希状态的接缝与块N+1开头的哈希状态的接缝匹配。

最终块的最终哈希状态将是整个有效负载的哈希。

为什么会这样?因为可以在接收到文件块时实时计算哈希值 - 而不是作为一个单独的耗时过程 - 在接收到所有文件块之后。


编辑: 基于 cmets:

这是一个粗略的状态哈希状态解决方案:

创建一个大的随机文件(100MB):

dd if=/dev/urandom of=large.bin bs=1048576 count=100

使用外部工具验证哈希:

$ shasum -a 256 large.bin 
4cc76e41bbd82a05f97fc03c7eb3d1f5d98f4e7e24248d7944f8caaf8dc55c5c  large.bin

在上述文件上运行playground code

...
...
...
offset: 102760448   hash: 8ae7928735716a60ae0c4e923b8f0db8f33a5b89f6b697093ea97f003c85bb56  state: 736861032a24f8927fc4aa17527e1919aba8ea40c0407d5452c752a82a99c06149fd8d35000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006200000
offset: 103809024   hash: fbbfd2794cd944b276a04a89b49a5e2c8006ced9ff710cc044bed949fee5899f  state: 73686103bdde167db6a5b09ebc69a5abce51176e635add81e190aa64edceb280f82d6c08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006300000
offset: 104857600   hash: 4cc76e41bbd82a05f97fc03c7eb3d1f5d98f4e7e24248d7944f8caaf8dc55c5c  state: 73686103c29dbc4aaaa7aa1ce65b9dfccbf0e3a18a89c95fd50c1e02ac1c73271cfdc3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000

最终的哈希匹配。

尝试使用偏移量和中间散列状态。该文件将是seeked 到此偏移量,从该点恢复哈希计算:

$ ./hash -o 102760448 -s "736861032a24f8927fc4aa17527e1919aba8ea40c0407d5452c752a82a99c06149fd8d35000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006200000"
offset:  103809024  hash: fbbfd2794cd944b276a04a89b49a5e2c8006ced9ff710cc044bed949fee5899f  state: 73686103bdde167db6a5b09ebc69a5abce51176e635add81e190aa64edceb280f82d6c08000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006300000
offset:  104857600  hash: 4cc76e41bbd82a05f97fc03c7eb3d1f5d98f4e7e24248d7944f8caaf8dc55c5c  state: 73686103c29dbc4aaaa7aa1ce65b9dfccbf0e3a18a89c95fd50c1e02ac1c73271cfdc3e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000

我们得到与以前相同的最终哈希。

注意:这确实会暴露哈希内部状态,因此请注意这可能需要的security implications。对于较大的块大小,这应该不是问题。

【讨论】:

  • 请记住,许多散列库不支持捕获或恢复中间状态,因此您可能必须修改现有代码或手动实现散列算法。 (很好的答案,读者可能会认为这很容易。)
  • 32 字节(对于 SHA-256,这恰好与最终哈希的大小相同,但这不是通用的)
  • 午餐后,我将更新答案,说明如何恢复哈希求和......
  • 实际上看起来比这更容易,我再看一遍,您需要做的是将返回的 hash.Hash 接口转换为 encoding.BinaryMarshalerencoding.BinaryUnmarshaler,这对于 stdlib 哈希器是允许的根据:golang.org/pkg/hash/#Hash
  • @Eloff 很有趣!我已经用一个工作示例更新了答案,包括这个发现。
【解决方案2】:

edit:这样做的目的是形成一种区块链,尽管 这些天这个词已经超负荷了。是为了诚信 目的,而不是工作证明。这个想法是散列块在 追随者节点,在集群领导者上将哈希合并为一个 有一个代表整个链的哈希,然后在前面加上 到要散列的新块。

这看起来像merkle tree

https://brilliant.org/wiki/merkle-tree/

Merkle 树是一种基于散列的数据结构,是一种泛化 的哈希列表。它是一个树形结构,其中每个叶子节点都是一个 一个数据块的散列,每个非叶子节点都是它的一个散列 孩子们。通常,默克尔树的分支因子为 2, 表示每个节点最多有 2 个子节点。

Merkle 树在分布式系统中用于高效数据 确认。它们是高效的,因为它们使用哈希而不是 完整的文件。哈希是对更小的文件进行编码的方法 比实际文件本身。目前,它们的主要用途是 点对点网络,例如 Tor、比特币和 Git。

看看那个实现https://github.com/cbergoon/merkletree

【讨论】:

    【解决方案3】:

    尝试将您已有的 SHA256 哈希值放入字符串中。然后使用 SHA256 或您选择的算法对该字符串进行散列。或者,您可以将原始数据块串在一起,然后对其进行哈希处理。但我认为“散列哈希”更快更干净。

    【讨论】:

      猜你喜欢
      • 2014-08-19
      • 1970-01-01
      • 1970-01-01
      • 2018-03-12
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-28
      相关资源
      最近更新 更多