Java 随机 UUID 是否可预测?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7532807/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 20:22:15  来源:igfitidea点击:

Are Java random UUID's predictable?

javasecurityrandomuuid

提问by ant-depalma

I would like to use a cryptographically secure primary key for sensitive data in a database - this cannot be guessable/predictable and it cannot be generated by the database (I need the key before the object is persisted).

我想对数据库中的敏感数据使用加密安全的主键 - 这无法猜测/预测,也不能由数据库生成(我需要在对象持久化之前使用密钥)。

I understand Java uses a type 4 UUID with a cryptographically secure random number generator, however I know the UUID isn't completely random so my question is how safe is it to assume that uuids cannot be predicted from a set of existing ones?

我知道 Java 使用带有加密安全随机数生成器的类型 4 UUID,但是我知道 UUID 不是完全随机的,所以我的问题是假设无法从一组现有的 uuid 中预测 uuid 有多安全?

采纳答案by Robert

Well if you want to know how random a UUID is you have to look onto the source.

好吧,如果您想知道 UUID 的随机性如何,则必须查看源。

The following code section is taken from OpenJDK7(and it is identical in OpenJDK6):

以下代码部分取自OpenJDK7(在OpenJDK6 中相同):

public static UUID 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);
    }

As you can see only 2 of 16 bytes are not completely random. In the sixth byte you lose 4 of 8 bits and on byte 8 you loose 2 bits of randomness.

如您所见,16 个字节中只有 2 个不是完全随机的。在第 6 个字节中,您丢失了 8 位中的 4 个,而在第 8 个字节中,您丢失了 2 位随机性。

Therefore you will get an 128 bit value with 122 bit randomness.

因此,您将获得具有 122 位随机性的 128 位值。

The only problem that may arise from the manipulation is that with a high chance your data can be identified as an UUID. Therefore if you want to hide it in other random data this will not work...

操作可能产生的唯一问题是,您的数据很有可能被识别为 UUID。因此,如果您想将其隐藏在其他随机数据中,这将不起作用......

回答by Peter Lawrey

If you want to generate a secure random key, I suggest you use SecureRandom. This can generate a key of any number of bits you require. Its slower than Random, but much more secure.

如果你想生成一个安全的随机密钥,我建议你使用 SecureRandom。这可以生成您需要的任意位数的密钥。它比随机慢,但更安全。

回答by MarianP

I have always thought that the 'cryptographically secure random number generator', (actually 'cryptographically strong pseudo random number generator') Javadoc note answers this.

我一直认为'加密安全的随机数生成器',(实际上是'加密强的伪随机数生成器')Javadoc 注释回答了这个问题。

http://download.oracle.com/javase/1,5.0/docs/api/java/util/UUID.html#randomUUID()

http://download.oracle.com/javase/1,5.0/docs/api/java/util/UUID.html#randomUUID()

From What Wikipedia says http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generatorsuch prediction would be a non-polynomial algorithm.

从维基百科所说的 http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator这样的预测将是一个非多项式算法。

If you need something 'truely' not just 'pseudo' random, you need to use something external, a hardware noise generator, random points generated after moving a mouse,...

如果您需要“真正”的东西而不仅仅是“伪”随机,您需要使用外部的东西,硬件噪声发生器,移动鼠标后生成的随机点,......

EntropyPoolseems to be helping with that, have not tried it yet http://random.hd.org/The way I understand it, it let's you download some real world noiseand use it in your Java app. It is not connected to java.util.UUID api, however, could probably be plugged in using the nameUUIDFromBytes(or other?) method.

EntropyPool似乎对此有所帮助,还没有尝试过 http://random.hd.org/根据我的理解,它让您下载一些真实世界的噪音并在您的 Java 应用程序中使用它。它没有连接到 java.util.UUID api,但是,可能可以使用nameUUIDFromBytes(或其他?)方法插入。

Would be cool if you let us know which way you decided to go.

如果您让我们知道您决定走哪条路,那就太好了。