为什么MD5的UUID不是个好主意?

时间:2009-08-18 13:12:49

标签: php cryptography md5

PHP有一个uniqid()函数,可以生成各种各样的UUID。

在用法示例中,它显示以下内容:

$token = md5(uniqid());

但在评论中,someone says this

  

从唯一ID生成MD5是   天真并且减少了很多的价值   唯一ID,以及提供   重要的(可攻击的)狭窄   MD5域名。这是深刻的   破碎的事情要做。正确的   方法是使用唯一ID   它自己的;它已经适应了   非碰撞。

为什么这是真的,如果是这样的话?如果MD5哈希对于唯一ID(几乎)是唯一的,那么从md5到uniqid会出现什么问题?

6 个答案:

答案 0 :(得分:34)

UUID是128位宽,并且具有生成方式固有的唯一性。 MD5散列是128位宽,并不保证唯一,只有较低的碰撞概率。 MD5哈希不小于UUID,因此它对存储没有帮助。

如果您知道散列来自UUID,则攻击起来要容易得多,因为如果您对生成它们的机器一无所知,那么有效UUID的域实际上是可以预测的。

如果您需要提供安全令牌,则需要使用cryptographically secure random number generator.(1)UUID并非设计为加密安全,仅保证唯一。由唯一机器标识符(通常是MAC)和时间限制的单调递增序列仍然是完全有效的UUID,但如果您可以从令牌序列中对单个UUID进行反向工程,则可以高度预测。

  1. 加密安全PRNG的定义特征是给定迭代的结果不包含足够的信息来推断下一次迭代的值 - 即生成器中存在一些未在数字中显示的隐藏状态,无法通过检查PRNG的一系列数字来推断。

    如果你进入数论,你可以找到从一系列生成值中猜测某些PRNG的内部状态的方法。 Mersenne Twister是这种发电机的一个例子。它具有隐藏的状态,它曾经用于获得它的长时间但它不具有加密安全性 - 你可以采用相当小的数字序列并使用它来推断内部状态。完成此操作后,您可以使用它来攻击加密机制,该机制依赖于保持该序列的秘密。

答案 1 :(得分:12)

请注意, uniqid()不会返回UUID ,而是根据当前时间返回“唯一”字符串:

$ php -r 'echo uniqid("prefix_", true);'
prefix_4a8aaada61b0f0.86531181

如果多次这样做,您将得到非常相似的输出字符串,熟悉uniqid()的每个人都会识别源算法。这样就很容易预测将要生成的下一个ID。

md5()输出的优点,以及特定于应用程序的盐字符串或随机数,更难以猜测字符串:

$ php -r 'echo md5(uniqid("prefix_", true));'
3dbb5221b203888fc0f41f5ef960f51b

与普通uniqid()不同,每微秒产生非常不同的输出。此外,它不会显示您的“前缀盐”字符串,也不会显示您在引擎盖下使用uniqid()。在不知道盐的情况下,猜测下一个ID非常困难(认为不可能)。

总之,我不同意评论员的观点,并且总是更喜欢md5() - 输出而不是普通uniqid()

答案 2 :(得分:5)

MD5ing UUID是没有意义的,因为UUID已经是唯一且固定长度(短),属性是人们经常使用MD5开始的一些原因。所以我认为这取决于你计划使用UUID做什么,但一般来说UUID与MD5的一些数据具有相同的属性,为什么两者都有?

答案 3 :(得分:2)

UUID已经是独一无二的了,所以无论如何MD5都没有意义。

关于安全问题,一般情况下,如果攻击者可以预测您将要生成的下一个唯一ID,则可能会受到攻击。如果已知您从UUID生成唯一ID,那么潜在的下一个唯一ID的集合会小得多,从而更有可能发生暴力攻击。

如果攻击者可以从您那里获得大量唯一ID,那么尤其如此,这就是猜测您生成UUID的方案。

答案 4 :(得分:2)

Version 3的UUID已经是MD5了,所以重新做这件事没有意义。但是,我不确定PHP使用的UUID版本。

答案 5 :(得分:0)

另外,MD5实际上是过时的,从2010年开始不会用于任何值得保护的东西--PHI,PII或PCI。美国联邦政府已经加强了这一点,任何不合规的实体都将支付大量的$$$罚款。