Database design 散列冲突-机会有多大?

Database design 散列冲突-机会有多大?,database-design,hash,Database Design,Hash,我的PHP站点上有一些创建随机散列的代码(使用sha1()),我用它来匹配数据库中的记录 发生碰撞的可能性有多大?我应该生成散列,然后首先检查它是否在数据库中(我宁愿避免额外的查询),或者根据它可能不会与另一个发生冲突的概率自动插入它。如果您假设SHA-1做得很好,您可以得出结论,两个给定消息具有相同散列的可能性为1/2^160(因为SHA-1产生160位散列) 2^160是一个非常大的数字。大约是10^48。即使数据库中有一百万个条目,新条目共享相同哈希值的几率仍然是十分之一^42 SHA-1

我的PHP站点上有一些创建随机散列的代码(使用
sha1()
),我用它来匹配数据库中的记录


发生碰撞的可能性有多大?我应该生成散列,然后首先检查它是否在数据库中(我宁愿避免额外的查询),或者根据它可能不会与另一个发生冲突的概率自动插入它。

如果您假设SHA-1做得很好,您可以得出结论,两个给定消息具有相同散列的可能性为1/2^160(因为SHA-1产生160位散列)

2^160是一个非常大的数字。大约是10^48。即使数据库中有一百万个条目,新条目共享相同哈希值的几率仍然是十分之一^42

SHA-1已经被证明是相当好的,所以我认为你根本不需要担心碰撞

作为补充说明,在使用SHA-1时,请使用PHP的raw_输出特性,因为这将导致字符串变短,从而使数据库操作更快


编辑:为了解决生日悖论,一个包含10^18(一百万)个条目的数据库发生冲突的几率约为1/0.0000000000003。真的不值得担心。

SHA-1生成160位长的摘要。因此,只要少于2^(160/2),您就安全了条目。除以2是由于。

来自第一原则:

SHA-1生成一个160位摘要。假设它均匀地使用整个位空间(这大概是它设计的目的),那么每个插入只有2^-160次发生冲突的机会

因此,对于每个插入,应该安全地假设没有冲突,如果有冲突,则处理错误

这并不是说你可以完全忽略碰撞的机会


生日悖论表明,由于存在O(N^2)种可能的冲突,数据库中至少发生一次冲突的可能性比您想象的要高。

如果您使用数字递增的ID作为输入,那么SHA-1发生冲突的可能性几乎为零


如果ID是唯一的输入,那么SHA-1似乎有点过头了——从32位整数生成160位哈希。我宁愿使用模幂运算,例如选择一个大的(32位)素数p,计算该组的模生成器g,然后使用g^ID。这将保证无冲突,并且只给出32位“哈希”.

问一个问题,如果发生冲突,你会付出什么代价。如果这是一个免费网站,那就罚款。如果你经营一家赚钱的企业,而过度委托会让你损失一百万美元的合同,那么我会三思

我认为你走错了方向。
我认为您需要保留唯一的ID,但您希望确保用户不能手动更改ID

一种方法是将ID和ID的散列(带有一些额外数据)放入链接中

例如:(我的PHP已经生锈了,所以一般的算法是:)


然后,当您收到一个请求时,只需验证您是否可以从ID重新生成哈希。这确实会使您面临攻击,从而计算出“我的私有字符串”,但这将非常困难,并且您始终可以附加用户无法直接使用的其他唯一内容(如会话ID).

其他评论已经涵盖了可能性,但是如果你从实际角度看待这一点,那么你可以自己得到一个明确的答案


您自己说过要对顺序ID进行哈希运算。编写测试用例很容易。遍历~100000000个ID并检查冲突。这不会花费很长时间。另一方面,您可能会在整个过程中耗尽四分之一的内存。

使用对称加密方案和ng>专用服务器密钥用于在将ID(和其他值)发送到客户端时对其进行加密,并在接收时再次解密。请注意,加密功能同时提供机密性和完整性检查

这允许您在与DB通话时使用合理的值,而不会发生任何冲突,在与客户端通话时具有很高的安全性,并将您登陆的概率降低约2^160


另请参见!

为什么不做一些确保不会发生冲突的事情,并确保没有人可以更改GET参数来查看他们不应该查看的内容:使用salt,将id及其哈希组合起来

$salt = "salty";
$key = sha1($salt . $id) . "-" . $id;
// 0c9ab85f8f9670a5ef2ac76beae296f47427a60a-5
即使您无意中发现两个具有完全相同的sha1哈希值的数字(使用salt),那么$key仍然会不同,您将避免所有冲突。

我不认为sha1()会给您带来任何麻烦,弱随机数生成更可能发生冲突


Stefan Esser在这个主题上写得很好。

有一个非常简单的规则来确定任何哈希算法是否会发生冲突。如果算法的输出范围是有限的,那么迟早会发生冲突。

尽管SHA1有很大范围的2^160散列可能性,但它仍然是一个有限的数字。然而,可以传递给该函数的输入实际上是无限的。如果输入数据集足够大,冲突必然会发生。

发生冲突的机会有多大? n个散列与S个不同可能散列总数碰撞的确切概率为:

(哈希函数的完美行为,生日悖论,等等…)

你无法直接计算,因为这是一个巨大的数字,所以我们使用极限并做出两个假设:

根据这两个假设,碰撞概率可通过以下公式计算:

现在,您可以计算n条记录的碰撞概率
$salt = "salty";
$key = sha1($salt . $id) . "-" . $id;
// 0c9ab85f8f9670a5ef2ac76beae296f47427a60a-5