1

I want to generate a random, cryptographically secure double in a very large range, say -Double.MAX_VALUE to Double.MAX_VALUE.

Based on existing StackOverflow questions (1 2 3 4 5 6) you may think that using min + new SecureRandom().nextDouble() * range would suffice, but Double.MAX_VALUE - -Double.MAX_VALUE overflows and becomes infinite!

To solve that, this StackOverflow answer suggests using ThreadLocalRandom.nextDouble(min, max). While this method is indeed capable of spanning the range I need it to, this implementation is not cryptographically secure!

How can I securely generate a random number within such a large range?

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
FWDekker
  • 1,823
  • 2
  • 20
  • 26
  • How about `SecureRandom.doubles(min, max)`? – shmosel Jul 18 '17 at 17:21
  • 1
    Does this answer your question? (With a `SecureRandom`.) https://stackoverflow.com/a/20079474/367273 – NPE Jul 18 '17 at 17:25
  • @shmosel Using `doubles(-Double.MAX_VALUE, Double.MAX_VALUE)` will always generate the same value of 1.7976931348623155E308, though I do not understand why. – FWDekker Jul 18 '17 at 17:27
  • @NPE If I slightly change the implementation to accept a custom `min` and `max`, it definitely solves my problem! – FWDekker Jul 18 '17 at 17:47

1 Answers1

1

I don't think this is possible. One of the requirements for cryptographic security is that the numbers should be indistinguishable from values selected uniformly at random.

If you choose 264 numbers in the range from −10308 to +10308, then two adjacent numbers will be separated by the rather large distance of 2.0E+308 / 2**64, which is about 1.08E+289.

Since a double-precision number has a 53-bit significand, then most of these numbers will be indistinguishable anyway. For example, adding 1.08E+289 to 1.0E+307 has absolutely no effect when working with double precision arithmetic.

Even if you do manage to find a way of mapping 264 values into this range, you'll probably still be vulnerable to birthday attacks. In general, you need at least 80 bits to provide a useful level of protection.

r3mainer
  • 23,981
  • 3
  • 51
  • 88
  • Wouldn't this mean that generating numbers from `0` to `Double.MAX_VALUE` is unsafe as well? – FWDekker Jul 19 '17 at 11:34
  • 1
    @FWDekker I think the best you can do is use [the method that NPE linked to in the comments](https://stackoverflow.com/a/20079474/367273). This won't give you a uniform distribution, and will need additional checks to handle special values like signed zeros and denormal values. I have no idea what your aim is, but I'm sure you would probably be better off working with random integers (preferably 80 or 128 bits) instead of faffing about with doubles. – r3mainer Jul 19 '17 at 11:47
  • You bring up a good point: What is my aim? I was reminded by another SO question that the range of integers representable by a double is _not_ continuous, something that I implicitly assumed. My aim is to securely generate a random value in the continuous integer range, which does not cause the problems I mentioned in my question. – FWDekker Jul 19 '17 at 14:55
  • 1
    The largest continuous range of integers that can be represented exactly in double precision floats is from -2^53 to +2^53. So you could, I suppose, generate a random integer in this range and convert it to a double. This range is rather too small for cryptographic applications, I think. – r3mainer Jul 19 '17 at 15:36
  • 1
    FWDekker: In fact, floating-point numbers are practically never used in security applications, with the exception of differential privacy and lattice-based cryptography. Rather, security applications use random _integers_ instead. Does your security use case rely on random _floating-point numbers_ rather than integers? – Peter O. Jul 01 '20 at 11:20