Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does SecureRandom guarantee distinct values each time?

I need to generate cryptographically secure, random and unique strings each of which will be used as an access token actually. For this purpose, I plan to use Java's SecureRandom class. But, I'm not sure that SecureRandom guarantees the uniqueness. In other words, does SecureRandom produces a different value on each time of the generation?

It seems like creating the instance with a seed value (i.e. new SecureRandom(byte[] seed)) may work. But, I'm not sure of that. Moreover, this answer states that the seed is neither safe nor portable. Does seed value serve my purpose?

If you have suggestions other than SecureRandom I want to hear them also.

like image 226
ovunccetin Avatar asked May 20 '26 09:05

ovunccetin


2 Answers

No, a SecureRandom instance does not guarantee unique results. If it did guarantee that, it wouldn't be entirely random, as you would know that you couldn't get a result that you already received.

Setting the seed value does not improve this situation. It also doesn't make it worse, because the seed you pass is added (supplements) the seed that was internally generated by the SecureRandom implementation.

If you want guaranteed unique random numbers, you need to keep all the previously generated numbers, and then check when you generate new number if it has already been returned. If it has, you need to generate a new number (and repeat the check).

However, if the number that you generate is significantly large, the chance of generating a non-unique number becomes insignificantly small. Try generating a number of 256 bits or more (32 bytes). This is also the mechanism the UUIDs use to generate "unique" numbers. These are also not guaranteed to be unique, but you'd have to wait a very, very long time (on average) before you get a duplicate.

like image 169
Erwin Bolwidt Avatar answered May 22 '26 23:05

Erwin Bolwidt


You could leverage the Stream API support for generating an IntStream from the SecureRandom:

SecureRandom random = new SecureRandom();
OfInt iterator = random.ints().distinct().iterator();

int random = iterator.next();

The ints method returns an "effectively unlimited stream of pseudorandom int values", which you can make distinct and obtain an iterator over the elements.

Given that there are 2^32 possible values, I would guess this should be enough for practical usages.

like image 24
M A Avatar answered May 22 '26 21:05

M A