哈希字节块的异或是否安全,不会发生冲突?



我想为数百万个URL中的每一个创建一个哈希或校验和,以便相同的URL(在清除后(具有相同的哈希/校验和。

如果我生成URL的SHA-1(20字节(或SHA-256散列(32字节(,并通过对散列的每个8字节块进行异或运算将它们存储为大整数(8字节((这里是C#代码示例(,那么它仍然安全吗?我读过一些人说应该没事,但没有找到任何可信的消息来源。

据我所知,[1,5]和[5,1]的XOR是相同的,尽管它们是不同的序列,所以散列XOR技术可能会导致冲突。在这种情况下,像MurMur、FNV或xxHash这样的非加密哈希算法是否更适合我的用例,因为它需要最少的碰撞机会和良好的性能(不一定是最快的(?

简单回答:没有。8字节(64位(的散列将不太可靠来区分"数百万";的URL。

见下表:https://en.wikipedia.org/wiki/Birthday_problem#Probability_table

该表指示了每个给定数量的元素发生碰撞的概率。这里的判断都取决于两件事:你的集合中有多少元素,以及你对";"可靠";。

对于一个打算重复工作的软件,您可能应该评估:

  • 您期望出现的元素(URL(的最大数量,特别是当您逐渐添加到集合中时
  • 在软件的预期使用寿命内,您的软件将被使用的不同数据集的数量(或次数(
  • 您的软件在每个周期/或其使用寿命内的可接受错误率是多少
  • 修复一个错误的代价有多高——是内存中的散列&你只需要重新运行,或者你是在DB/文件中持久地收集这些文件,并且它们的回收成本很高

有一些计算器可以帮助计算。我用过这个:https://kevingal.com/apps/collision.html将其切换到"位"模式,而不是桶模式。

评估示例:

  • 每年添加1000万个URL
  • 软件寿命为20年&一年运行100次,但始终是同一个数据集
  • 我们只接受百万分之一的错误机会
  • =2亿个URL
  • =>通过计算器,74位的散列会给你大约1.1e-6的碰撞机会,但只适用于128位

另一种可能的评估:

  • 每个数据集中有5000万个URL或元素
  • 软件寿命为20年&每年运行100次,每次使用独立的数据集
  • 我们一生只接受一百万分之一的错误机会
  • =5000万个URL
  • =软件需要运行2000次,使用寿命概率为百万分之一
  • =>因此,一次运行中出错的概率需要为~5e-10
  • =>通过计算器,一个81位的散列会给你5.2e-10的碰撞机会——只需要128位

结论:保持简单&健壮,使用128位散列

最后几句话:异或既不必要也不可取;只需将散列截断为要使用的字节数。

如果健壮的唯一性很重要,我建议您使用加密级别的哈希,如SHA-256或SHA-1。出于安全目的,SHA-256比SHA-1更强(更能抵抗密码攻击(。这两种算法仍然非常快。

最新更新