哈希碰撞 - 有什么机会?

时间:2008-11-18 05:55:45

标签: database-design hash

我的PHP网站上有一些代码可以创建一个随机哈希(使用sha1()),我用它来匹配数据库中的记录。

发生碰撞的几率是多少?我应该生成哈希值,然后检查它是否在数据库中(我宁愿避免额外的查询)或自动插入它,基于它可能不会与另一个冲突的概率。

12 个答案:

答案 0 :(得分:27)

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

2 ^ 160是一个非常大的数字。它大概是10 ^ 48。即使您的数据库中有一百万个条目,新条目仍然可以共享相同的哈希值,这仍然是1/10 ^ 42的可能性。

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

作为旁注,在使用SHA-1时使用PHP的 raw_output 功能,因为这将导致更短的字符串,从而使您的数据库操作更快一些。

编辑:为了解决生日悖论,一个包含10 ^ 18(百万亿)条目的数据库有可能在0.0000000000003的碰撞中大约有1。 真的不值得担心。

答案 1 :(得分:16)

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

这允许您在与DB进行通信时使用敏感值而不会发生任何冲突,在与客户交谈时具有极高的安全性,并降低您在thedailyWTF上着陆的概率大约2 ^ 160

另见Pounding A Nail: Old Shoe or Glass Bottle?

答案 2 :(得分:14)

为什么不做一些保证没有碰撞的事情,以及确保没有人可以改变GET参数来查看他们不应该做的事情:使用salt,结合使用id和它的哈希。

$salt = "salty";
$key = sha1($salt . $id) . "-" . $id;
// 0c9ab85f8f9670a5ef2ac76beae296f47427a60a-5

即使你不小心偶然发现了两个具有完全相同的sha1哈希值(使用你的盐)的数字,那么$ key仍将是不同的,你将避免所有的冲突。

答案 3 :(得分:5)

如果你使用数字增加的ID作为输入,那么SHA-1将碰撞几乎为零。

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

答案 4 :(得分:4)

SHA-1产生160位长的摘要。因此,只要您的条目少于2 ^(160/2),您就是安全的。 2除法归因于birthday paradox

答案 5 :(得分:4)

从第一原则出发:

SHA-1生成160位摘要。假设它均匀地使用整个位空间(这可能是它的设计目的),那么每次插入时只有2 ^ -160的几率就会发生碰撞。

因此,对于每个插入,假设没有冲突应该是安全的,并且如果存在则处理错误。

这并不是说你可以完全忽略碰撞的可能性。

生日悖论表明,由于O(N ^ 2)可能的碰撞,数据库中至少有一次碰撞的可能性高于您的猜测。

答案 6 :(得分:2)

如果您必须对网址中的某些数据进行模糊处理以隐藏数据,那么您做错了。

答案 7 :(得分:1)

提出问题如果发生碰撞,您会花多少钱。如果这是免费网站罚款。如果你正在经营赚钱的业务并且覆盖将花费你一百万美元的合同,那么我会再想一想。

我认为你是以错误的方式解决这个问题 我认为您需要保留唯一ID,但您要确保用户无法手动更改ID。

实现此目的的一种方法是将ID和ID的哈希(带有一些额外数据)放在链接中。

例如:(我的PHP生锈,因此通用算法将是:)

id   = 5;
hash = hash("My Private String " + id)
link = "http://mySite.com/resource?id=" + id + "&hash=" + hash

然后,当您收到请求时,只需验证您是否可以从ID重新生成哈希值。这确实让你可以通过攻击来解决“我的私人字符串”问题,但这样做会非常困难,而且你总是可以附加一些其他不可用的东西(例如会话ID)。

答案 8 :(得分:1)

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

尽管SHA1具有非常大范围的2 ^ 160个哈希可能性,但它仍然是有限数。但是,可以在该函数上传递的输入实际上是无限的。给定足够大的输入数据集,必然会发生冲突。

答案 9 :(得分:0)

其他评论已经涵盖了你的概率,但如果你务实地看一下,那么你可以为自己找到一个明确的答案。

你自己说你将要记录你的顺序ID。编写测试用例很容易。迭代~100,000,000个ID并检查碰撞。这不用花很长时间。另一方面,你可能会在整个过程中耗尽内存。

答案 10 :(得分:0)

我不认为sha1()会给你带来任何麻烦,弱随机数生成更可能是碰撞的候选者。

Stefan Esser在这个主题上写了很好的article

答案 11 :(得分:0)

发生碰撞的机会是什么?

n 哈希与 S 发生冲突的 exact 概率为:

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

您将无法直接进行计算,因为这些数字很大,因此我们使用限制并做出2个假设:

使用这两个假设,可以用以下公式计算发生碰撞的可能性:

现在,您可以计算一些 n 条记录发生碰撞的可能性。对于sha1(S = 2 ^ 160)小于2 ^ 70的记录,这非常非常准确,近似值越差, n 方法就越接近2 ^ 80。

示例

例如,如果您想保存大量用户,特别是与世界上某人的数量相同(〜80亿),并且您使用sha1(S = 2 ^ 160),则发生碰撞的可能性是 2.5e-29 (请注意,这两个假设均成立)。为了给您提供参考,赢得欧洲百万大奖的可能性大约为 7e-9

好奇心:如何处理更大(更大?!)的数字?

无需第二个假设即可直接计算极限。

例如,第一次碰撞预计在 S 的平方根周围(在sha1 n = 2 ^ 80的情况下)。在该值下,第二个条件不成立,但我们可以直接使用以下方法计算极限:

约为40%。发生碰撞的可能性。