uniqid有多独特?

Gor*_*onM 74 php

这个问题并不是寻找解决方案的问题,更多的只是一个简单的好奇心问题.PHP uniqid函数有一个更多的熵标志,使输出"更独特".这让我想知道,当more_entropy为真时,这个函数有多大可能产生相同的结果,而不是.换句话说,启用more_entropy与禁用more_entropy时,uniqid的唯一性如何?启用more_entropy是否有任何缺点?

SW4*_*SW4 35

更新,2014年3月:

首先,重要的是要注意这uniqid有点用词不当,因为它不保证唯一的ID.

根据PHP文档:

警告!

此函数不会创建随机或不可预测的字符串.此功能不得用于安全目的.使用加密安全随机函数/发电机的加密安全散列函数来创建不可预知的安全ID.

此函数不会生成加密安全令牌,事实上,如果没有传递任何其他参数,则返回值与microtime()略有不同.如果需要生成加密安全令牌,请使用openssl_random_pseudo_bytes().


根据文档,将more-entropy设置为true可以生成更独特的值,但执行时间更长(尽管程度很小):

如果设置为TRUE,则uniqid()将在返回值的末尾添加额外的熵(使用组合的线性同余生成器),这会增加结果唯一的可能性.

注意这一行increases the likelihood that the result will be unique而不是那将保证唯一性.

你可以"无休止地"追求独特性,达到一定程度,并增强使用任何数量的加密程序,添加等等 - 这取决于目的.

我建议查看主要PHP主题的评论,特别是:

http://www.php.net/manual/en/function.uniqid.php#96898

http://www.php.net/manual/en/function.uniqid.php#96549

http://www.php.net/manual/en/function.uniqid.php#95001

我建议的是找出为什么你需要唯一性,是为了安全性(即添加到加密/加扰例程)?此外,它有多独特?最后,看看速度考虑.适用性将随着潜在的考虑因素而变化.

  • 我不知道这是否是显而易见的,但不要使用`uniqid`(或它的衍生物)来处理与安全相关的任何事情.PHP提供了大量的加密安全随机生成器,例如:`openssl_random_pseudo_bytes`.请使用正确的工具进行工作. (3认同)
  • 不知道为什么这个答案被接受。唯一!=随机/不可预测 (2认同)

dmp*_*dmp 15

只有当你检查它们不存在时,事物才是唯一的.使用什么函数生成"随机"字符串或ID并不重要 - 如果你不仔细检查它是不是重复,那么总有那种机会..;)

虽然uniqid基于当前时间,但上述注意事项仍然适用 - 它只取决于您将使用这些"唯一ID"的位置.这一切的线索就是"更独特"的地方.独特是独一无二的.你怎么能拥有或多或少独特的东西,对我来说有点混乱!

如上所述检查,并结合所有这些东西将让你最终得到一些接近唯一性的东西,但它的全部相对于密钥的使用位置和上下文.希望有所帮助!

  • "碰撞的机会是一万分之一"和"碰撞的变化小于同时被闪电击中的程序的每个用户"之间存在巨大的差异.一个好的RNG和一个好的种子生成的128位值非常接近"真正"独特而无关紧要,考虑到获得*可证明*(和不可预测)唯一的令人难以置信的高成本. (9认同)
  • 只是为了进一步说明你的观点@Michael:对于128位,你需要美国的每个人(3亿)每秒产生100万个数字,持续一天才能获得50%的碰撞几率......对于512比特,你需要地球上的每个人(70亿人)在接下来的10 ^ 47年内每秒产生1万亿个数字才有50%的碰撞几率...所以是的,有一个在随机数上有足够大的上限和足够好的RNG,你可以只用随机性来模拟唯一性...... (6认同)
  • "通过简单地将Bambleweeny 57 Sub-Meson Brain的逻辑电路连接到悬挂在强大的布朗运动生产商(比如一杯热腾腾的茶)中的原子矢量绘图仪,产生少量有限不可能性的原理当然是很好理解的". (4认同)

Mic*_*rdt 10

从关于PHP手册网站上的功能的讨论:

正如下面的其他人所说,没有前缀而没有"添加熵",这个函数只返回带有微秒计数器的UNIX时间戳作为十六进制数; 它或多或少只是microtime(),呈六角形.

[...]

另外值得注意的是,由于microtime()仅适用于具有gettimeofday()>存在的系统,而Windows本身并不存在,uniqid()可能只会在Windows环境中产生单秒分辨率的UNIX时间戳.

换句话说,没有"more_entropy",这个函数绝对可怕,永远不应该使用,期间.根据文档,该标志将使用"组合线性同余生成器"来"添加熵".嗯,这是一个相当弱的RNG.所以我完全跳过这个函数并使用基于mt_rand的东西和一个很好的种子来处理那些与安全无关的东西,并使用SHA-256作为东西.


Ree*_*ore 7

如果没有more_unique标志,它将返回带有微秒计数器的unix时间戳,因此如果两个调用在相同的微秒进行,那么它们将返回相同的"唯一"ID.

从那里开始,这是一个多么可能的问题.答案是,不是很好,但不是折扣程度.如果您需要一个唯一的ID并且经常生成它们(或使用其他地方生成的数据),请不要指望它绝对唯一.

  • 不管它信不信,它实际上叫做usleep(1)以确保永远不会发生! (19认同)
  • @Eli不确定是否拖钓,但显然情况并非如此,因为我正在运行这个重复:for($ i = 0; $ i <10; $ i ++)echo uniqid()."\n" 个; (2认同)
  • @ djule5不,不要拖钓:https://github.com/php/php-src/blob/af6c11c5f060870d052a2b765dc634d9e47d0f18/ext/standard/uniqid.c#L67你是在运行一个非常旧版本的PHP还是在平台上运行usleep不存在? (2认同)

Tgr*_*Tgr 5

源代码中的相关位是

if (more_entropy) {
    uniqid = strpprintf(0, "%s%08x%05x%.8F", prefix, sec, usec, php_combined_lcg() * 10);
} else {
    uniqid = strpprintf(0, "%s%08x%05x", prefix, sec, usec);
}
Run Code Online (Sandbox Code Playgroud)

所以more_entropy添加九个有点随机的十进制数字(php_combined_lcg()返回一个值(0,1)) - 那是 29.9 位熵,tops(实际上可能更少,因为 LCG 不是加密安全的伪随机数生成器)。