6

我想在一个可能永远不会有超过 10,000 条记录的数据库表中使用 PHP 生成的唯一 ID。我不希望创建时间可见或使用纯数值,所以我使用:

sha1(uniqid(mt_rand(), true))

使用哈希作为唯一 ID 是错误的吗?不是所有的散列都会导致冲突,或者在这种情况下不应该考虑它们的可能性很小吗?

还有一点:如果要散列的字符数小于 sha1 散列中的字符数,它不总是唯一的吗?

4

5 回答 5

8

如果您有 2 个密钥,则理论上的最佳情况是 2 ^ X 的碰撞概率,其中 X 是散列算法中的位数。“最佳情况”,因为输入通常是不使用完整字符集的 ASCII,加上散列函数分布不完美,因此它们在现实生活中的碰撞频率会超过理论上的最大值。

要回答你的最后一个问题:

还有一点:如果要散列的字符数小于 sha1 散列中的字符数,它不总是唯一的吗?

是的,这是真的。但是您会遇到另一个问题,即生成该大小的唯一键。最简单的方法通常是校验和,因此只需选择一个足够大的摘要,以使碰撞空间足够小以使您感到舒适。

正如@wayne 建议的那样,一种流行的方法是连接microtime()到您的随机盐(并base64_encode提高熵)。

于 2013-05-03T05:53:03.507 回答
3

使用 sha1(time()) 代替,然后您消除重复哈希的随机可能性,只要时间可以表示为比 sha1 哈希更短。(可能比你找到一个工作的 php 解析器要长;))

于 2013-05-03T05:58:17.490 回答
3

如果两个结局相同,那该有多可怕?墨菲定律适用——如果可以接受一百万比一甚至十万比一的机会,那么就继续吧!真正的机会要小得多——但如果你的系统一旦发生就会爆炸,那么你的设计缺陷必须首先得到解决。然后充满信心地进行。

这是概率的真正含义的问题/答案: SHA1 碰撞的概率

于 2013-05-03T05:45:37.797 回答
2

计算机随机实际上并不是随机的,你知道吗?假设您在 Unix 环境中,您可以从计算机获得的唯一真正随机是 from /dev/random,但这是一个阻塞操作,取决于用户交互,例如移动鼠标或在键盘上打字。读取/dev/urandom不太安全,但它可能比仅使用 ASCII 字符更好,并为您提供即时响应。

于 2013-05-14T23:00:23.713 回答
0

sha1($ipAddress.time()) 导致任何人都不可能同时使用相同的 IP 地址

于 2021-07-11T19:22:40.083 回答