如果您尝试重新创建已拆分为块(例如 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。对于较大的块大小,这应该不是问题。