具有接近 SHA-1 碰撞可能性的快速散列函数

Fast hash function with collision possibility near SHA-1

我正在使用 SHA-1 检测程序处理文件中的重复项。它不需要加密强度高并且可以是可逆的。我找到了这个快速哈希函数列表 https://code.google.com/p/xxhash/ (list has been moved to https://github.com/Cyan4973/xxHash)

如果我想要更快的函数和接近 SHA-1 的随机数据的碰撞,我应该选择什么?

也许 128 位散列足以删除文件重复数据? (对比 160 位 sha-1)

在我的程序中,哈希是根据 0 - 512 KB 的块计算的。

也许这会对您有所帮助: https://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed

collisions rare: FNV-1, FNV-1a, DJB2, DJB2a, SDBM & MurmurHash

我不知道 xxHash,但它看起来也很有前途。

Mu​​rmurHash 非常快,版本 3 支持 128 位长度,我会选择这个。 (在 Java 和 Scala 中实现。)

Google 开发并使用(我认为)FarmHash 进行性能关键型哈希。来自 project page:

FarmHash is a successor to CityHash, and includes many of the same tricks and techniques, several of them taken from Austin Appleby’s MurmurHash.

...

On CPUs with all the necessary machine instructions, about six different hash functions can contribute to FarmHash's lineup. In some cases we've made significant performance gains over CityHash by using newer instructions that are now commonly available. However, we've also squeezed out some more speed in other ways, so the vast majority of programs using CityHash should gain at least a bit when switching to FarmHash.

(CityHash 已经是 Google 的性能优化哈希函数系列。)

它是一年前发布的,那时它几乎可以肯定是最先进的,至少在已发布的算法中是这样。 (否则 Google 会使用更好的东西。)很有可能它仍然是最好的选择。

事实:

  1. 好的哈希函数,特别是密码函数(如 SHA-1), 需要相当长的 CPU 时间,因为他们必须兑现一些 在这种情况下对您不是很有用的属性;
  2. 任何哈希函数只会给你一个确定性:如果两个文件的哈希值不同,则文件肯定不同。但是,如果它们的散列值相等,那么文件也可能相等,但是确定 "equality" 是否不仅仅是散列冲突的唯一方法是回退到二进制比较两个文件。

结论:
在你的情况下,我会尝试像 CRC32 这样更快的算法,它几乎具有你需要的所有属性,并且能够处理超过 99.9% 的情况,并且只求助于较慢的比较方法(如二进制比较)来排除误报。在绝大多数比较中快得多可能会弥补没有 "awesome" 均匀性(可能会产生更多的碰撞)。

128 位确实足以检测不同的文件或块。碰撞的风险是无限小的,至少只要不尝试故意碰撞。

如果您要跟踪的文件或块的数量保持 "small enough"(即不超过几百万),64 位也可以证明足够好。

确定散列的大小后,您需要一个具有一些非常好的分布属性的散列,例如在您的 link.

中以 Q.Score=10 列出的散列

由于与您的情况唯一相关的哈希算法 属性 是碰撞概率,您应该估计它并选择满足您要求的最快算法。

如果我们假设您的算法具有绝对一致性,则使用具有 d 个可能值的散列的 n 个文件之间发生散列冲突的概率将是:

例如,如果您需要在一百万个文件中的碰撞概率低于百万分之一,您将需要具有超过 5*10^17 个不同的哈希值,这意味着您的哈希需要具有至少 59 位。让我们四舍五入到 64 来说明可能存在的不均匀性。

所以我想说任何像样的 64 位散列对你来说都应该足够了。更长的哈希将进一步降低碰撞概率,但代价是计算量更大和哈希存储量增加。较短的缓存(如 CRC32)将要求您编写一些明确的冲突处理代码。

这在某种程度上取决于您要在迭代中计算多少 哈希。 例如,64 位哈希在计算了 600 万个哈希后达到了 1000000 分之一的碰撞概率。

参考:Hash collision probabilities

查看 MurmurHash2_160。它是产生 160 位输出的 MurmurHash2 的修改。

它并行计算 MurmurHash2 的 5 个唯一结果并将它们彻底混合。碰撞概率等同于基于摘要大小的 SHA-1。

它仍然很快,但 MurmurHash3_128、SpookyHash128 和 MetroHash128 可能更快,尽管碰撞概率更高(但仍然不太可能)。还有 CityHash256,它产生 256 位输出,应该也比 SHA-1 更快。