如何组合 sha 哈希?



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

编辑:这样做的目的是形成一种区块链,尽管这个术语现在非常超载。这是出于完整性目的,而不是工作证明。这个想法是在追随者节点上对块进行哈希处理,将哈希组合成一个在集群领导者上,以有一个代表整个链的哈希,然后将其附加到要哈希的新块之前。

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

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

如果您尝试重新创建已拆分为块(例如大小为 10MB(的大型有效负载(例如 1GB 文件(的哈希,则需要在整个集合上计算哈希(MD5、SHA-256 等(。因此,使用此示例时,您无法添加100 个分块哈希来重新创建原始文件的哈希。然而。。。

您可以为每个块发送 2 个值:

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

当块被流式传输时,可以验证块末尾的哈希状态的接缝N与块N+1开头的哈希状态的接缝相匹配。

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

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


编辑:基于评论:

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

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

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

使用外部工具验证哈希:

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

在上面的文件上运行此游乐场代码。

...
...
...
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

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

注意:这确实会暴露哈希内部状态,因此请注意这可能带来的安全隐患。对于较大的块大小,这应该不是问题。

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

这看起来像一个merkle tree

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

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

默克尔树用于分布式系统以获得高效数据 验证。它们很高效,因为它们使用哈希而不是 完整文件。哈希是对小得多的文件进行编码的方法 比实际文件本身。目前,它们的主要用途是 点对点网络,如Tor,比特币和Git。

看看该实现 https://github.com/cbergoon/merkletree

尝试获取您已经拥有的 SHA256 哈希并将它们放在一个字符串中。 然后使用 SHA256 或您选择的算法对该字符串进行哈希处理。 或者,您可以将原始数据串在一起,然后对其进行哈希处理。 但我认为"哈希哈希"更快、更干净。

最新更新