1

Using SecureRandom is there a guarantee that 2 sequential calls will not return the same number?
If this is a strict requirement from client API side, is the following loop in the code redundant or not?

Random random = SecureRandom.getInstance("SHA1PRNG");  
long value1 = (long)(r.nextDouble() * LIMIT) + 1;  
long value2 = (long)(r.nextDouble() * LIMIT);  

while(value1 == value2) {  
   value2 = (long)(r.nextDouble() * LIMIT);  
}
Cratylus
  • 52,998
  • 69
  • 209
  • 339

3 Answers3

5

I wouldn't expect there to be. Each call should be independent - requiring the next call to not give the same result as the previous one means it's not as random, IMO.

To take a smaller example, imagine we didn't have nextDouble but a method which returned a value in the range 1 to 3 inclusive. By removing the possibility of returning the same value twice, you've effectively constrained each call to a 50/50 choice, for no obvious reason. You'd be giving extra information about the next call to anyone who could observe "this" call.

Now obviously with double there's a much bigger range - so there's a much smaller of two genuinely randomly-picked values being the same. Not quite 1 in 264, but pretty large.

You've reduced that somewhat by your arithmetic, of course - even if nextDouble() did guarantee to always return different values, it's entirely possible for two double values to have the same result when multiplied by LIMIT and then cast to long. Imagine if LIMIT is 2 for example... how many possible values would you expect to see?

So no, I don't think the code you've got is redundant if you have a strict client requirement.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
3

No. It is not guaranteed and guaranteeing that would make it less secure because it could be possible for an attacker to exploit the knowledge that you will never get the same number on successive calls. It is completely possible for a random sequence of numbers to contain "runs" of numbers. If you have a list of numbers out of which you have an equal chance of picking any number, then it is very possible that you can pick the same number twice. Of course, the probability of that happening is lower than the probability of getting a sequence of two different numbers, but it is not zero.

Also, one of the requirements for a CSPRNG is that given a state, you should not be able to predict the next state (i.e., all numbers in your range have an equal probability of showing up). But with your requirement, you can predict that if your random number generates a number x in the range 0 to n, then in the next call you will get any number but x.

While there may be some sort of state-machine inside the CSPRNG, each call is essentially independent of previous calls and should not be affected by them.

If you're going for uniqueness, you should use something like a UUID. These can be generated randomly with the advantage that you get uniqueness (if you are using a CSPRNG and the seed source has sufficient entropy).

If the requirement is that the client doesn't get two identical random numbers, then the code is not redundant. But it will violate the "randomness" property; how important that is, depends on your particular situation.

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
  • I think successive 128-bit outputs of a CSPRNG are more likely to be unique than two random UUIDs. Either has an infinitesimal chance of duplication, otherwise they wouldn't qualify as "random", but many bits of the UUID are predictable, where all 128 bits of the CSPRNG are unpredictable. Otherwise, good answer. – erickson Jul 15 '15 at 20:19
  • @erickson Yes most definitely. When it comes down to the math, there is a greater chance of getting the same v4 UUID twice than getting the same 128-bit number twice. But as you said, the chance is infinitesimal for practical purposes. – Vivin Paliath Jul 15 '15 at 20:24
2

By calling nextDouble() you're actually calling Random.nextDouble() - SecureRandom extends Random and doesn't override nextDouble()

According to the documentation of nextDouble() - there is no guarantee that 2 sequential calls will not return the same number - that said, the likelihood of it to happen is very low.

Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129