我想提高对大型文件进行哈希处理的性能,例如,以数十亿字节为单位。

通常,您通常使用哈希函数对文件的字节进行哈希处理(例如SHA-256,尽管我极有可能会使用Skein,所以与从[快速] SSD读取文件所花费的时间相比,散列会更慢。我们将此方法称为1。

其思想是在8个CPU上并行散列文件的多个1 MB块,然后将串联的散列散列为单个最终散列。让我们将此方法称为2,如下所示:





我想知道这个想法是否合理,以及多少“安全性”与在整个文件范围内进行一次哈希相比,丢失(就更可能发生冲突而言)。

例如:

让我们使用SHA-256变体SHA-2并将文件大小设置为2 ^ 35 = 34,359,738,368字节。因此,使用简单的单遍(方法1),我将获得整个文件的256位哈希值。

将其与以下内容进行比较:

使用并行哈希(即方法2),我将文件分成1个MB的32,768个块,使用SHA-256将这些块散列为256位(32字节)的32,768个散列,将这些散列连接起来,并对最终的1,048,576个字节进行最后的散列数据集以获取整个文件的最终256位哈希值。

就冲突而言,方法2的安全性是否比方法1的安全性低?也许我应该将问题改写为:方法2是否使攻击者更容易创建散列为与原始文件相同的哈希值的文件,当然,除了琐碎的事实之外,因为哈希可以在N cpus上并行计算吗?

更新:我刚刚发现我在方法2中的构造与哈希列表的概念非常相似。但是,前一句中的链接所引用的Wikipedia文章并未详细介绍哈希列表相对于方法1的冲突机会的优劣,方法1是文件的普通旧哈希,而仅顶部哈希使用哈希表的

评论

仅供参考:它起源于Stack Overflow,然后在此处交叉发布。

#1 楼

无论如何,如果您想使用Skein(SHA-3候选对象之一):它具有用于树哈希的“操作模式”(配置变体),就像您的方法2一样。

它在操作内部进行此操作,因为在单个块上多次调用UBI。这在Skein规范文件(1.3版)的3.5.6节中进行了描述。



您将需要1 MB的叶子大小(因此,Y_l =对于512位变体为14,对于256为15,对于1024为13),最大树高Y_m = 2。 (该图显示了一个Y_m> = 3的示例。)

本文并未真正包含对树形哈希模式的任何密码分析,而是包含了该事实(甚至可能提及)用于密码哈希处理)似乎意味着作者认为它至少与“标准”顺序模式一样保存。 (在证明文件中也没有提及。)


从理论上讲:
在哈希函数中查找冲突的大多数方法都依赖于在哈希函数中查找冲突。底层压缩函数f:S×M-> S(它将先前的状态与数据块映射到新的状态)。

这里的冲突是其中之一:


一对消息和一个状态,使得f(s,m1)= f(s,m2)
两个状态对,一个消息块,使得f(s1, m)= f(s2,m)
一对消息和一对状态,使得f(s1,m1)= f(s2,m2)。

第一个是最容易利用的-只需修改消息的一个块,然后将所有其他块都设置为相同。

要使用其他块,我们还需要对前一个块的压缩功能进行前映像攻击,这通常被认为更加复杂。

如果我们遇到第一种类型的冲突,则可以在树版本以及顺序版本(即最低级别)中利用它。为了在较高级别上产生冲突,我们再次需要在较低级别上进行原像攻击。

因此,只要哈希函数(及其压缩功能)具有原像抵抗能力,树形版本就不会碰撞弱点要比“长流”之一。

评论


$ \ begingroup $
本文似乎没有提到这种类似于Merkle Tree的树哈希方法是否比顺序方法安全,该方法是我的问题的症结所在。
$ \ endgroup $
– Michael Goldshteyn
2011年8月10日在20:31

$ \ begingroup $
这不是回答问题...不?
$ \ endgroup $
–JérômeVerstrynge
11年10月10日在20:35

$ \ begingroup $
不,据我所知,事实并非如此。看到我的第一条评论。
$ \ endgroup $
– Michael Goldshteyn
2011年8月10日在20:41

$ \ begingroup $
@Michael:对不起,这条评论太长了。我添加了一些有关抗碰撞性的理论考虑。
$ \ endgroup $
–PaŭloEbermann
2011年8月10日在22:24

$ \ begingroup $
因此,也许我的问题简化为:在长输入数据大小(例如数十GB)或短输入数据大小(例如1 MB)的情况下,查找冲突是否容易,轻视它需要更长的时间来哈希更长的输入。
$ \ endgroup $
– Michael Goldshteyn
2011年8月11日12:59

#2 楼

实际上,您所描述的基于树的哈希(您的方法2)在某种程度上降低了对第二个原像的抵抗力。

对于具有$ n $位输出的哈希函数,我们期望抵抗力: />

冲突最多$ 2 ^ {n / 2} $,
第二个前映像最多$ 2 ^ {n / 2} $,
前映像最多$ 2 ^ n $。

这里的“工作量”是根据对简短的“基本”输入的哈希函数调用次数(对于SHA-256,按512位块进行数据处理,这是处理一个块的成本)。

让我们看一下第二个原像的情况:您有一个大文件$ m $,攻击者知道;攻击者的目标是找到一个不同于$ m $的哈希值相同的$ m'$。假设您使用了“方法2”,该方法将$ m $拆分为32768个子文件$ m_i $,分别对它们进行哈希处理,然后对串联的$ h(m_i)$进行哈希处理。如果攻击者发现与$ m_i $不同的$ m'_i $,但哈希值相同(对于$ i $的32768个值中的任何一个),攻击者将成功。这可以称为“多目标第二原像攻击”。因此,他可以尝试使用随机字符串,直到其中之一的哈希值与32768哈希值$ h(m_i)$之一匹配为止。攻击的有效成本为$ 2 ^ {n-15} $,这比具有$ n $位输出的良好哈希函数的预期$ 2 ^ n $要少。

(详细而言,由于攻击者需要他的$ m'_i $具有与$ m_i $相同的长度,因此在处理每个$ m_i $的第一个块之后,他将以SHA-256状态为目标,并使用随机的-阻止字符串。)

现在不要惊慌,$ 2 ^ {n-15} $仍然很高。确实,很容易看出,成功的第二次原像攻击必定意味着在树中某处发生了碰撞,因此电阻不会低于$ 2 ^ {n / 2} $,并且您使用的函数恰好具有256位输出,因此$ 2 ^ {n / 2} $太高了。

从密码学的角度来看,基于树的哈希函数所提供的功能还不如我们预期的给定输出大小所能提供的理论上最大的安全性好。这可以通过大多数情况下的修复,方法是将每个单独的哈希函数调用与即将处理的子文件的编号“合并”。正确的做法并不容易。在Skein规范中,如@Paŭlo所述,描述了一种基于树的哈希方法;可以避免我刚才详述的问题;但是,基于树的Skein不是作为SHA-3竞争的一部分而研究的“ the Skein”(“ SHA-3候选Skein”纯粹是顺序的),因此尚未受到外界的广泛审查。同样,“ the” Skein本身仍然是一种新设计,我个人建议不要匆忙处理。可以通过年老获得安全性。

作为补充,Skein优于SHA-256的速度优势取决于所使用的体系结构。特别是在32位系统上,Skein运行缓慢。最近的x86处理器具有SSE2单元,即使在32位模式下也可以提供64位计算,因此,只要使用本机代码(带有内在函数或汇编语言的C),Skein在过去几年的任何PC上都可以快速运行。在其他架构上,情况也不尽如人意。例如,在ARM处理器(甚至是智能手机或平板电脑中最新的大型处理器)上,SHA-256将比Skein快2至3倍。实际上,在32位MIPS和ARM平台上,以及在32位x86处理器上运行的纯Java实现上,SHA-256的速度要比所有其他SHA-3候选速度更快(请参阅此报告)。

评论


$ \ begingroup $
Skein的树哈希模式试图通过对各个块使用不同的调整来避免此问题,因此,根据其在树中的位置,块具有不同的哈希。好点,我之前没有注意到这一点。 (我只是希望我能再次投票赞成。)
$ \ endgroup $
–PaŭloEbermann
2011年8月10日在22:21



$ \ begingroup $
我不确定我是否理解您对两种方法强度差异的解释。不过很明显,如果空间不成问题,则可以在块上并行执行SHA-512(这更昂贵),这样一来,就可以从并行运算和块运算中减去任何丢失的比特与串行执行SHA-256相比,位深度要大得多(512与256)。
$ \ endgroup $
– Michael Goldshteyn
2011年8月11日在2:52



$ \ begingroup $
Skein也是如此,实际上它在64位(x86)硬件上的Skein-1024 / 1024实现中非常快。可以提出一种方法3,在对Skein-1024 / 1024值进行并行计算后,将其折叠以创建一个512位哈希,其安全性不低于顺序Skein-512 / 512哈希(也就是说,在计算中只使用了512位状态。虽然,我不清楚如何进行这种折叠,除了可能通过截断最高或最低有效512位之外。
$ \ endgroup $
– Michael Goldshteyn
2011年8月11日在2:53



$ \ begingroup $
@Michael:Skein标准使输出长度完全独立于状态大小。输出长度甚至还有一个配置选项。 (这确保了512位输出的输出不是截断的1024位输出的输出。)
$ \ endgroup $
–PaŭloEbermann
2011年8月11日12:10



$ \ begingroup $
我知道-那就是我使用512/512语法(具有512位状态的512位哈希)显示的内容。我的观点是,如果我将1024位散列和1024位状态用于(并行处理的)块,并将512位散列(也可能具有1024位状态)用于哈希的最终散列,则实际上散列比对整个文件按顺序执行的具有512位状态的512位散列要强。或者,也许我错了。
$ \ endgroup $
– Michael Goldshteyn
2011年8月11日12:55



#3 楼

修订:提议的构造很好,尤其是:



至少具有与SHA-256一样安全的抵御碰撞攻击的能力,这就是对手使用以下命令构造两个文件的能力:相同的散列;
对于第一和第二原像攻击而言,其安全性几乎与SHA-256一样,这是指对手能够构造(对于第一原像)具有任意散列值的文件(对于第一原像),或者(对于第二个原图像)具有与任意给定文件相同的哈希值的文件。

该构造会稍微降低最大抵抗哈希值的第二个原图像抵抗力。但是对于SHA-256,第二原像的抵抗力似乎仍然不比对RD Dean在其1999年论文中提出的Merkle-Damgård散列的一般攻击所允许的允许的差(第5.3.1节),J。Kelsey对其进行了更好地暴露和完善。和B. Schneier在关于$ n $位哈希函数的第二张原像中,其工作量不到$ 2 ^ n $。

评论


$ \ begingroup $
请注意,Merkle-Damgard的第二个图像前安全性损失相似,因此,与SHA-2相比,安全性损失仅是由于树所增加的额外压缩量所致,而压缩量所占的比例不大。解决方法也非常相似,要么添加唯一的节点标签,要么使用宽管道。
$ \ endgroup $
– CodesInChaos
2014年7月9日在13:08

$ \ begingroup $
@CodesInChaos:非常正确!我根据您的观察确定了答案。
$ \ endgroup $
–fgrieu♦
2014年7月9日15:21

#4 楼

方法2的安全性不亚于方法1。

这是为什么:散列函数具有的密码属性是,在计算上无法找到任何两个散列为相同值的不同原像,这在计算上是不可行的。方法1直接依赖于此。但是,如果我们想举一个与方法2发生冲突的示例,则意味着:


两次运行之间对最终哈希的输入有所不同(在这种情况下,因为我们有两个输入实例导致完全相同的输出,所以这是基础哈希函数的冲突),或者
最终哈希的输入完全相同(所以,因为输入在某处有所不同) ,这意味着至少有一个初始哈希具有不同的输入但具有相同的输出,再次说明,这是基础哈希函数的冲突。

在两种情况下,我们都可以恢复冲突,这表明哈希函数不像我们希望的那样具有抗冲突性,而且如果我们在方法1中将这两个输入用作文件,方法1也将遭受冲突。

评论


$ \ begingroup $
问题是,使用方法2,我们可以在最终的哈希中发生冲突,而在中间的哈希中没有冲突。另外,如果将一个大文件分成1 MB的块,则有可能在其中一个块上发生冲突,但这不会导致最终哈希的冲突。这就是为什么方法2失去任何哈希强度的原因还不清楚。
$ \ endgroup $
– Michael Goldshteyn
2011年8月11日在2:49



$ \ begingroup $
实际上,很明显,方法2至少与方法1一样强,就这种强烈的意义而言:如果您有一种算法在方法2中找到了概率为p且计算量为N的碰撞,那么您还拥有一种在方法1中查找冲突的方法,该方法以概率p和计算工作量N + \ epsilon(其中\ epsilon表示检查子哈希并发现内部发生冲突的工作量)而工作
$ \ endgroup $
–雨披
2011年8月11日下午13:57

#5 楼


就碰撞而言,方法2的安全性是否比方法1的安全性低?



您正在产生更多的值,这些值可以用于尝试碰撞,但是如果您选择足够大的哈希空间,则其区别与海洋中的分子与海洋中的液滴之间的区别是相同的。...完全不必担心!

#6 楼

如果哈希函数适用于一般用途,则适用于此用途。只要攻击者无法找到两个散列为相同值的二进制字符串,您的方法就是安全的。如果您不确定所使用的哈希算法是否正确,则选择了错误的算法。

说攻击者有32,768次机会可以找到冲突,因此比较容易,这是无效的。通过一次尝试32,768种不同的可能输入,他可以轻松地为单个二进制图像查找冲突。没有理由期望某些障碍会比其他障碍强或弱,因此没有理由认为更多的机会会使其变得更容易。 (因为他可以复制,所以还是只有一次机会。)

#7 楼

拖曳方法具有大致相同的安全性。在SHA-2和其他加密哈希函数中,消息分为512位块。提到PaŭloEbermann的好方法可以提供更高的安全性。如果方法1是安全的,则没有已知的针对方法2的攻击。<​​br />
编辑:
@Pornin描述:


攻击将是$ 2 ^ {n-15} $,小于对于具有$ n $位输出的良好哈希函数的预期$ 2 ^ n $。





阻力不会低于$ 2 ^ {\ frac {n} {2}} $


评论


$ \ begingroup $
是的,所有加密散列函数都将消息分成多个块。但是,状态从一个大块转移到下一个大块(即,每个后续大块的哈希值取决于所有先前的大块)。方法2保持块独立,直到最终散列为止,因此我的问题是与方法1相比是否不足。
$ \ endgroup $
– Michael Goldshteyn
2011年8月10日在21:20