这个问题实际上并不是寻找解决方案的问题,而仅仅是出于好奇。PHP uniqid函数具有一个更熵的标志,以使输出“更唯一”。这让我想知道,当more_entropy为true时(而不是true时),此函数多次产生相同结果的可能性有多大。换句话说,启用more_entropy时与禁用时相比,uniqid的唯一性如何?始终启用more_entropy是否有任何弊端?
这个问题实际上并不是寻找解决方案的问题,而仅仅是出于好奇。PHP uniqid函数具有一个更熵的标志,以使输出“更唯一”。这让我想知道,当more_entropy为true时(而不是true时),此函数多次产生相同结果的可能性有多大。换句话说,启用more_entropy时与禁用时相比,uniqid的唯一性如何?始终启用more_entropy是否有任何弊端?
more_entropy大约是30位的熵(九位十进制数字),微秒部分大约是20位(六位十进制数字),其余部分从何而来?您需要从100,000年的范围内选择第二个,以获得42位的熵。
Answers:
2014年3月更新:
首先,必须注意这uniqid是一个误称,因为它不能保证唯一的ID。
根据PHP文档:
警告!
此函数不会创建随机的或不可预测的字符串。不得出于安全目的使用此功能。使用加密安全的随机函数/生成器和加密安全的哈希函数来创建不可预测的安全ID。
和
此函数不会生成加密安全的令牌,实际上,如果未传递任何其他参数,则返回值与microtime()几乎没有什么不同。如果您需要生成加密安全的令牌,请使用openssl_random_pseudo_bytes()。
根据文档,将更多熵设置为true会生成一个更唯一的值,但是执行时间更长(尽管程度很小):
如果设置为TRUE,则uniqid()将在返回值的末尾添加额外的熵(使用组合线性同余生成器),这将增加结果唯一的可能性。
请注意这行increases the likelihood that the result will be unique,并非那会保证唯一性。
您可以“无限地”争取唯一性,并使用任意数量的加密例程,添加盐等来增强它-这取决于目的。
我建议您查看有关主要PHP主题的评论,尤其是:
http://www.php.net/manual/zh/function.uniqid.php#96898
http://www.php.net/manual/zh/function.uniqid.php#96549
http://www.php.net/manual/zh/function.uniqid.php#95001
我建议您弄清楚为什么需要唯一性,这是出于安全性考虑(例如,添加到加密/加扰例程中)?另外,它需要有多独特?最后,看一下速度注意事项。适应性将随着基本注意事项而变化。
uniqid(或它的派生)用于与安全相关的任何事情。PHP提供了很多加密安全的随机生成器,例如:openssl_random_pseudo_bytes。请使用正确的工具进行作业。
do{} while(collision)。例如,当生成上载文件的路径时,我会使用这种方法。
只有当您检查事物还不存在时,它们才是唯一的。用来生成“随机”字符串或ID的函数无关紧要-如果您不仔细检查它是否不是重复项,那么总会有这种机会。
尽管uniqid是基于当前时间的,但上面的注意事项仍然适用-它仅取决于您将在哪里使用这些“唯一ID”。这一切的线索是它说“更加独特”。独特就是独特。您如何拥有或多或少独特的东西,这让我有些困惑!
如上进行检查,并将所有这些东西组合在一起,将使您最终获得接近唯一性的东西,但其全部与使用键的位置和上下文有关。希望有帮助!
10^47几年中每秒产生1万亿个数字,才有50%的机会发生碰撞...所以是的,具有足够大的上限在随机数和足够好的RNG上,您可以只用随机性来模拟唯一性...
rand(),那么他们在第一次迭代中就有90%以上的机会发生碰撞。另外,如果您需要独特性,甚至.001%的碰撞几率也太大。
从PHP手册站点上有关该函数的讨论:
如下所述,没有前缀,也没有“加熵”,此函数仅返回UNIX时间戳,并以十六进制数字形式添加微秒计数器。它或多或少是microtime(),为十六进制格式。
[...]
另外值得一提的是,由于microtime()仅适用于具有gettimeofday()> present的系统,而Windows本机不支持,因此uniqid()在Windows环境中可能仅产生一秒分辨率的UNIX时间戳。
换句话说,如果没有“ more_entropy”,该函数绝对是可怕的,绝对不能使用。根据文档,该标志将使用“组合线性同余生成器”来“添加熵”。好吧,这是一个相当弱的RNG。因此,我将完全跳过此功能,对与安全无关的事物使用基于mt_rand的种子,并为其提供良好的种子,而对与安全无关的事物使用SHA-256。
如果没有more_unique标志,它将返回带有微秒计数器的unix时间戳,因此,如果在同一微秒内进行了两次调用,则它们将返回相同的“唯一” id。
从那里开始,这是一个可能性的问题。答案不是,但是不是一个可打折的程度。如果您需要唯一的ID,并且经常生成它们(或使用其他位置生成的数据),则不要指望它是绝对唯一的。
源代码中的相关位是
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);
}
因此,more_entropy增加了9个有点随机的十进制数字(php_combined_lcg()返回的值(0,1))-熵的29.9位,最高(实际上可能更少,因为LCG并不是安全加密的伪随机数生成器)。
uniqid与more_entropy集给出仅熵的约92位(23个hexbits)。要了解为什么这样做不利于独特性,请参见《生日问题...》