计算文件哈希值的最快方法是什么?

3

很多文件将存储在数据库中,我需要文件哈希值来唯一标识文件是否被更改。 (通常用于Windows个人防火墙部分)

2个回答

19

如果我正确理解了“用作Windows个人防火墙”的部分,MD5算法并不是一个好的选择。

存在一种成功攻击MD5算法的方法,使你可以找到一个产生相同哈希值的不同消息,而且与暴力破解相比,这种攻击需要的工作量相对较小。这种攻击曾经没有实际影响,例如当MD5被用于哈希密码等情况时。在此期间,已经发现了新的攻击方式,因此MD5和SHA-1都可以以惊人的速度进行哈希/碰撞,使用这些“老式”哈希算法来破解完整的数据库“适当加盐”和单哈希用户密码不仅完全可行,而且已经被证明。

然而,在特定的应用程序中,如“确保该文件未被篡改”,这种攻击一直存在问题,而不仅仅是最近的问题。MD5可以安全地检测位错误或意外修改,但是试图绕过您个人防火墙的恶意软件可能通过找到感染的二进制文件的碰撞使哈希值匹配原始文件而相对容易地绕过整个安全性。

在这种情况下,您应该使用SHA-256 [更新:在此期间,SHA-3已经推出,虽然我个人不同意NIST的优胜者选择(或排除某些非常好的第二轮候选人的模糊标准),但使用SHA-3(Keccak)或SHA-3决赛选手中的一种是一个更安全的选择。所有的决赛选手都由经验丰富的团队精心设计并经过了非常彻底的分析,目前没有一个真正的攻击或已知的问题可能导致实际的攻击,并且它们都有“更多的位数”(这本身并不意味着太多,但更多的位数也没有什么坏处)]。

同时,记得总是除了使用哈希之外也要保存文件长度,这样即使使用较弱的哈希算法也会大大增加其安全性,���成本很小。如果可以的话,计算两个不同的哈希值。对于攻击者来说,找到一个与之产生碰撞的消息比找到一个长度完全相同且相互碰撞的消息要容易得多,甚至是在两个不同的哈希算法中发生碰撞的消息。

由于带宽(磁盘和内存)是计算哈希的一个重要因素,所以即使是同时计算单个哈希或两个哈希,速度也可能相近。我曾经在计算CRC并用块密码加密相同块后观察到这种效果。无论是否计算CRC,整体运行时间的差异都不到1%,基本上是一项免费操作。

如果您认为有很好的理由不使用众所周知的标准哈希算法(例如性能限制),则可以构建自己的安全哈希算法。使用Merkle–Damgård构造(或更近期的HAIFA),您可以将任何安全块密码转换为安全哈希函数。例如,使用固定密钥对每个输入块进行AES加密,并在加密下一个块之前将输出异或到下一个块。最后一个块后的输出即为哈希值。

虽然“自行构建”通常不是个好主意,但在这种情况下可能确实存在有效的理由,因为AES快速且在最新的处理器中得到支持。在我的机器上,AES的运行速度大约为130MB/s。在i7(具有硬件支持)上,互联网上报道其速度约为570MB/s。

关于I/O限制,Unwind是正确的,磁盘可以很好地成为限制因素,尽管并不一定会如此。内存映射是您的朋友,特别是在您的特定情况下。

如果您检查适用于防火墙权限的文件,则这些文件将是已加载到RAM中的可执行文件(毕竟,它们正在被执行!)。因此,映射已经在RAM中的页面只需要添加一个页表项,几乎没有操作。即使数据不在RAM中,内存映射的性能(和易用性)也是绝对惊人的,在需要速度时我很少使用其他方法。


2
哦,我的天啊,这个问题已经两年了!为什么没有人告诉我,现在我感觉很愚蠢... - Damon
1
你的回答仍然很好,因此它具有附加价值。 - Not Available
又过了一年,你的回答仍然很有价值。加个赞 :) - Jochem

4

当然,这通常是不可能的。很多人仍然使用哈希算法来实现这个目的,MD5 是一种流行的算法,可以为文件生成一个 128 位的“签名”,当文件内容发生更改时有很高的概率会发生变化。

在一般情况下,您需要查看文件的每一位才能将其包含在哈希中,而性能可能会受到 I/O 的限制。这是对文件中所有数据进行顺序扫描,每读取一个新字节就更新哈希算法的状态。在现代 CPU 上,后者比前者更快。这篇相当老的分析显示,在 Pentium 90 MHz CPU 上大约可达到 ~45 MB/s 的速度。


你混淆了位和字节。那个网站显示的是约45 Mb/s而不是45 MB/s。2.0字节每时钟周期是不现实的。现代CPU对于MD5处理大约需要5个时钟周期每字节。 - CodesInChaos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接