【问题标题】:UUID.randomUUID() vs SecureRandomUUID.randomUUID() 与 SecureRandom
【发布时间】:2017-02-08 18:13:28
【问题描述】:

我试图了解使用 UUID.randomUUID() 相对于 SecureRandom 生成器的优势,因为前者在内部使用 securerandom。

【问题讨论】:

  • 取决于您要执行的操作。如果您需要 UUID,请使用 UUID.randomUUID()。如果您需要其他形式的随机性,请直接使用SecureRandom
  • 比较起来有点奇怪,好像它们是可以互换的。他们做两种不同的事情。 SecureRandom 是一个随机数生成器。 UUID.randomUUID() 生成一个UUID,它不仅仅是一个随机数。
  • 有什么问题? UUID 表示具有定义格式的特殊类型的 id,而 SecureRandom "just" 生成随机数。它们是不同的东西。
  • @siarheib 是的,但那又怎样?它们仍然是两个具有不同目的的类,您使用哪一个取决于您需要做什么。
  • 它并不能真正保证唯一性,但您可以放心地假设 UUID实际上是唯一的(发生冲突的可能性非常小,以至于你不必担心它)。

标签: java uuid secure-random


【解决方案1】:

好吧,source code 显示 UUID.randomUUID 使用 SecureRandom

public static UUID  [More ...] randomUUID() {
    SecureRandom ng = numberGenerator;
    if (ng == null) {
        numberGenerator = ng = new SecureRandom();
    }
    byte[] randomBytes = new byte[16];
    ng.nextBytes(randomBytes);
    randomBytes[6]  &= 0x0f;  /* clear version        */
    randomBytes[6]  |= 0x40;  /* set to version 4     */
    randomBytes[8]  &= 0x3f;  /* clear variant        */
    randomBytes[8]  |= 0x80;  /* set to IETF variant  */
    return new UUID(randomBytes);
}

如您所见,您可以使用其中任何一种,但在安全的 UUID 中,您有 6 个非随机位,如果您很挑剔,这可能会被视为劣势。

【讨论】:

  • 是的,所以如果我想生成唯一的 ID,我可以使用 SecureRandom 本身来实现,对吗?这和获得 4 类 UUID 一样好吗?但也许我可以生成具有比 122 更多随机填充的位数的唯一 ID。正确吗?
  • 是的,你可以这样做。但是,如果您想将其用作 UUID,我建议您使用 randomUUID。这 6 位在 UUID 规范中,很高兴遵守规范:en.wikipedia.org/wiki/…
  • 哦,或者,我认为,我应该研究一下私有构造函数 UUID(randomBytes); 到底是什么。是的。
  • 私有构造函数UUID(byte [] arr)不对随机生成的字节数组进行任何操作,从而改变其值!
  • @uoyilmaz 你能引用源代码摘录吗,也许有链接?
【解决方案2】:

随机数有随机重复的机会。随机性越低(除非有一些协调),产生相同数字两次的机会就越大。

https://en.wikipedia.org/wiki/Birthday_problem
随着您生成更多随机数,重复相同数字的机会会增加,因为每个 id 都必须与其他每个 id 不同。

SecureRandom 允许您选择所需的随机数。让它太小,它们很有可能会被重复。您可以在几分之一秒内获得重复的随机 32 位 id。

UUID 将标准设置为 128 位(或者正如 uoyilmaz 指出的那样,122 位是随机的)这对于大多数用例来说已经足够了。但是,如果您想要一个随机字符串,我会很想使用比 16 更多的位和/或更高的基数。例如 Java 支持基数 36 和 64,这意味着您可以有更短的 id,或者相同长度的 ID 具有更多随机性。

注意:UUID 格式在它的转储中有多个 -,虽然我没有看到它们的值,它们只是使字符串更长。

【讨论】:

  • 破折号只是为了便于阅读;如果你看不到它们的用途,你可能是一个机器人:P
  • @MaartenBodewes ;) - 似乎放在了一些有意义的分组中,但我不知道它是什么。
【解决方案3】:

感谢您提供的所有技术答案。我自己也对导致我来到这里的两者之间的差异感到困惑。但是后来,我突然想到:如果你只调用一次函数,那么没有区别,因为这两种方法都会生成一个无法预先计算的数字。但是如果多次调用该函数,那么它们在这里会有所不同,因为统计正态分布是随机数生成器的属性,而这不是 UUID 的属性。 UUID 力求唯一性,实际上它使用您计算机的 MAC 硬件地址、当前纪元秒数等推导出提供的数字。最终,如果您对 UUID 值进行循环调用,它不会在统计上呈正态分布。

【讨论】:

    【解决方案4】:

    UUID 不是一个随机数:它是一个通用的唯一 ID。你可以确定没有人可以生成相同的十六进制字符串。

    随机数是另一回事:它不是十六进制字符串,也不是普遍唯一的。

    this library 提供了一个更高效、更完整的 UUID 生成器。

    【讨论】:

    • "您可以确定没有人可以生成相同的十六进制字符串。" - 这可能会产生误导:您可以生成相同的 uuid,但如果您遵守规则,这种情况发生的可能性很小。
    • 理论上可以发生碰撞,但概率非常低:en.wikipedia.org/wiki/…
    • 如果您想要一个真正的通用唯一 ID,并且该值的保密性并不重要(因为它很容易预测),那么类型 1 的 UUID 肯定是唯一的,并且relative Java class 可以提供最后一个。
    • @Sandro - java.util.UUID not 生成类型 1 UUID。从中生成 UUID 的唯一方法是自己提供原始数据或使用 randomUUID 生成类型 4 UUID。
    • @Julse - 你是对的:我刚刚更好地阅读了UUID class 的文档。通过java.util.UUID类,只能生成类型3和类型4。
    猜你喜欢
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多