26

I am trying to understand the advantages of using UUID.randomUUID() over SecureRandom generator as the former uses securerandom internally.

User3518958
  • 676
  • 1
  • 6
  • 19
  • 2
    Depends on what you're trying to do. If you need UUIDs, then use `UUID.randomUUID()`. If you need your randomness in some other form, use a `SecureRandom` directly. – Andy Turner Sep 30 '16 at 08:26
  • 6
    It's a bit strange to compare them, as if they are interchangeable. They do two different things. `SecureRandom` is a random number generator. `UUID.randomUUID()` generates an `UUID`, which is not just a random number. – Jesper Sep 30 '16 at 08:27
  • 1
    What's the problem? `UUID` represents a special type of id with a defined format while `SecureRandom` "just" generates random numbers. They are different things. – Thomas Sep 30 '16 at 08:27
  • 1
    UUID.randomUUID() uses SecureRandom actually. At least in [OpenJDK](http://hg.openjdk.java.net/sandbox/jdk7/jdk/file/3a3c4785e7a7/src/share/classes/java/util/UUID.java#l171) – siarheib Sep 30 '16 at 08:30
  • 3
    @siarheib Yes, but so what? They are still two classes that have different purposes and which one you'd use depends on what you need to do. – Jesper Sep 30 '16 at 08:35
  • 1
    @Andy Turner, actually I need to generate unique IDs to be used as correlationIDs. I had considered two options : SecureRandom (though it will give random number and does not guarantee uniqueness) 2. UUID.randomUUID(). UUID guarantees unique ID. But when I looked at the source for this method, it uses SecureRandom and generates value with 122 bits filled randomly. Hence wondered why would one o for using this method. – User3518958 Sep 30 '16 at 09:32
  • 1
    I think I need to understand how UUID.randomUUID() guarantees uniqueness despite of just using the secure random. – User3518958 Sep 30 '16 at 09:35
  • 1
    @Jesper, yes I agree we can't compare them considering the purposes they serve. But I am confused about how UUID.randomUUID ensure uniquness looking at its source code. – User3518958 Sep 30 '16 at 09:43
  • 3
    It doesn't really **guarantee** uniqueness, but you can safely assume that UUIDs are **practically** unique (the chance of a collision is so small that you don't need to worry about it). – Jesper Sep 30 '16 at 09:47
  • 1
    See [Random UUID probability of duplicates](https://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates) if you want to learn more about what the chances of a collision are. – Jesper Sep 30 '16 at 09:50
  • 1
    That's just a link, but you can find the source material [here](http://www.h2database.com/html/advanced.html#uuid). Yes, it is unique simply because the change of generating the same UUID is so small you can safely ignore it. – Maarten Bodewes Dec 20 '18 at 16:23

4 Answers4

47

Well, the source code shows UUID.randomUUID uses 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);
}

As you can see, you can use either, but in a secure UUID you have 6 non-random bits, which can be considered a disadvantage if you are picky.

uoyilmaz
  • 3,035
  • 14
  • 25
  • 2
    Yeah, so if I want to generate unique IDs, I will be able to do so using SecureRandom itself right? Would that be as good as getting type 4 UUIDs. But may be I can generate unique IDs with more number of bits filled randomly than 122. Is that correct? – User3518958 Sep 30 '16 at 09:53
  • 4
    Yes, you can do that. But, if you want to use it as a UUID, I would suggest using randomUUID. Those 6 bits are in the UUID specification, and it's nice to stay true to specifications: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29 – uoyilmaz Sep 30 '16 at 10:02
  • 1
    Ohk, or, I think, I should look into what exactly the private constructor UUID(randomBytes); does. – User3518958 Oct 01 '16 at 10:55
  • 2
    The private constructor UUID(byte [] arr) does not perform any operations on the randomly generated byte array so as to change its value! – User3518958 Oct 01 '16 at 14:41
  • 1
    @uoyilmaz Would you cite the source code excerpt, perhaps with a link? – Basil Bourque Oct 02 '16 at 20:14
15

Random numbers have a random chance of being repeated. The lower the randomness (unless there is some co-ordination), the greater the chance of producing the same number twice.

https://en.wikipedia.org/wiki/Birthday_problem
As you produce more random numbers the chance of the same number being repeated increases as every id must be different to every other id.

SecureRandom allows you to choose how many bit of randomness you want. Make it too small and there is a good chance they will be repeated. You can get duplicate random 32-bit id in a fraction of a second.

UUID sets the standard at 128 bits (or as uoyilmaz points out, 122 bits are random) This is enough for most use cases. However if you want a random String, I would be tempted to use more bits and/or a higher base than 16. Java for example support base 36 and 64 which means you can have shorter ids, or more randomness for the same length ID.

Note: UUID format has multiple - in it's dump though I don't see the value of them, they just make the string longer.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 4
    The dashes are just for human readability; you may be a cyborg if you don't see the use of them :P – Maarten Bodewes Dec 20 '18 at 16:26
  • 1
    @MaartenBodewes ;) The `-` appears to be placed in some meaningful grouping, but I don't know what it is. – Peter Lawrey Dec 24 '18 at 19:08
  • 2
    The dashes make it easier for human readers to identify the records in the layout: https://en.wikipedia.org/wiki/Universally_unique_identifier – troyfolger Apr 13 '22 at 20:46
  • 1
    The use of hex in the canonical representation is actually much more wasteful than the hypens (eg a base62 representation is 22 chars). Between that and the hyphens, it's a great pity that it's so common to serialise UUIDs in this format as strings in transport or storage. – Adrian Baker Jun 11 '22 at 00:39
  • 1
    @Adrianbaker I favour using a distributed high resolution timestamps with a configured hostId embedded. It's easier to read and only 64-bit, faster too. http://blog.vanillajava.blog/2022/01/distributed-unique-time-stamp.html – Peter Lawrey Jun 12 '22 at 18:12
1

Thanks for all the provided technical answers. I, myself, was also baffled by the difference between the two which led me here. But then, a thought dawned on me: If you only call the function once, then there is no difference as both method generates a number that could not be pre-calculated. But if call the function several times, then they differ here because a statistical normal distribution is a property of a random number generator whereas this is not a property of a UUID. UUID strives for uniqueness and in fact it derives the provided number using your computer's MAC hardware address, the current epoch seconds etc. And eventually, if you for-loop call the UUID values it will not be statistically normally distributed.

daparic
  • 3,794
  • 2
  • 36
  • 38
-4

The UUID is not a random number: it is a universal unique ID. You can be sure that no one can generate the same hexadecimal string.

A random number is another story: it is not an hexadecimal string and it is not universally unique.

A more efficient and completed generator of UUIDs is provided by this library.

sandromark78
  • 148
  • 1
  • 4
  • 13
    "You can be sure that no one can generate the same hexadecimal string." - that might be misleading: you _can_ generate the same uuid but if you follow the rules it is very unlikely that this happens. – Thomas Sep 30 '16 at 08:31
  • 2
    You can have collisions theoretically, but it's a very low probability: https://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates – uoyilmaz Sep 30 '16 at 08:41
  • 1
    If you want a real universal unique ID and the secrecy of that value is not important (because it is easy to predict), an **UUID of type 1** is certainly unique and the [relative Java class](https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html) can provide this last one. – sandromark78 Sep 30 '16 at 12:40
  • 1
    @Sandro - java.util.UUID does *not* produce type 1 UUIDs. The only way of producing a UUID from it is either to give it the raw data yourself or use `randomUUID` to generate a type 4 UUID. – Jules Aug 16 '17 at 07:34
  • 1
    @Julse - You are right: I have just read better the documentation at the [UUID class](http://docs.oracle.com/javase/8/docs/api/java/util/UUID.html). By java.util.UUID class, it is possible only to generate type 3 and type 4. – sandromark78 Aug 16 '17 at 09:39
  • 1
    Each pseudorandom string may be generated multiple times, as number of digits or letters is finite. – stinger Dec 15 '17 at 11:51
  • 1
    UUID's generally rely on the fact that it is highly unlikely to generate identical random numbers. If your secure random number is large enough (say, 122 bits, as a type 4 UUID) it is very likely unique. There is some value in linking to the Apache libs (preferably while indicating what you're linking to) but if there is misinformation in the answer I have to downvote. – Maarten Bodewes Dec 20 '18 at 16:33