在用 md5 散列后使用 java.util.UUID 是一个不错的选择吗?

is using the java.util.UUID after hashing it with md5 a good option?

我看到了下面这段代码。

.
. // some code
.
String guid = NetworkUtil.md5(java.util.UUID.randomUUID().toString())
.
. // guid is being used 
.

这是个好方法吗,hashing a Version 4 UUID with MD5

根据UUID规范,UUID本身生成的UUID的唯一性非常好,碰撞的几率非常非常小。那么上面的这段代码实际上是不是通过使用 MD5 对其进行散列来降低唯一性的质量,MD5 现在是一种过时的散列机制并且容易发生冲突和攻击。

您只能通过散列来使可能唯一的值变得更糟。它不能变得更好或 "more unique"。因此,除了将其转换为可在需要 md5 哈希字符串的情况下使用的统一格式之外,通过这样的哈希处理没有任何好处。

让我们从这个开始:

According to UUID specification, UUID itself is very good in uniqueness of the generated UUID's and chances of collision are very very very small.

其实并没有这么说。不能这么说,因为那没有意义。

事实上,如果 UUID 规范说明了类型 4 UUID 的唯一性,它会说它们仅与随机数来源 一样好。这取决于平台以及 RNG 和 UUID 实施的质量。如果我们可以假设一个完美的 1 随机数源,那么任意两个(单独生成的)UUID 相同的概率为 2122;即非常非常小。另一方面,如果随机数来源较差,则成对碰撞的概率会增加。

So isn't this above piece of code actually reducing the quality of uniqueness by hashing it with MD5 which is an obsolete hashing mechanism now and prone to collisions and attacks.

是的。但 MD5 并不是真正的问题。

正如@Doug Stevenson 所说,对 UUID 进行哈希处理并不会减少发生冲突的可能性。甚至对于没有已知弱点的哈希算法也是如此。无论是哪种算法,散列 UUID 都有可能增加冲突的可能性2.

所以基本上,散列单个 UUID 没有意义。

但是,如果您需要一个比第 4 类 UUID 具有更小冲突概率的标记,您可以将 N 个第 4 类 UUID 连接成一个字节数组,然后为该数组创建一个散列。如果您有一个(强大的)M 位哈希算法,并且为您的 UUID 生成器提供了完美的随机数来源,那么发生碰撞的几率应该大约为 2min(M, 122 * N).


1 - 也就是说,随机位的来源,除了 50% 的正确概率外,某人(攻击者)不可能预测序列中的下一位。

2 - 如果有任何两个不同的 UUID 具有相同的哈希值,就会发生这种情况。即使对于强大的哈希算法也是可能的...除非您将其定义为衡量强度的标准。