I have a need to generate a key consisting of a given number of random characters that will be used to access resources via a public API. It should not be possible to predict the key. This is done in Java. I can use a SecureRandom instance but this can be slow because it needs to gather enough entropy from the underlying system. Some quick tests show that generating 1000 keys of length 100 already takes an appreciable amount of time.

Things are very speedy if instead the SecureRandom is used to generate a seed for a regular random number generator, like so:

Random random = new Random(secureRandom.nextLong());
Stream.generate(() -> random.nextInt(upperBound))
        ... // use random ints to create key

Given that the random generator will be used to generate integers with a bound, I believe it isn't possible to predict the remainder of a key from its first few characters. Likewise the possession of one key would not be enough to predict the next key because a new Random is created for each key generation with a seed of the secure generator, so even if you could deduct what the seed for one key was you wouldn't know how the next one will be seeded.

Is this sufficiently secure? One objection I can think of is that the characters generated by the regular random generator are fully predictable based on its seed. With the seed being a Java long value, this effectively reduces the possible generated keys to 2^64 which eliminates the advantage of the vast space that a key of dozens of random characters including letters and numbers would have. Is this a fatal flaw? Can the scheme be improved without the need for getting every integer from the secure generator?

  • It might be better to simply change the JVM source of random data to use /dev/urandom instead of /dev/random, or just read directly from /dev/urandom. I don't specifically know if what you're doing is secure, but I do know that /dev/urandom is highly secure, unpredictable, and re-seeded. docs.oracle.com/cd/E13209_01/wlcp/wlss30/configwlss/… Dec 12 '19 at 16:16
  • Or possibly just use a different lib that uses /dev/urandom. I'd avoid rolling your own solution if possible. Dec 12 '19 at 16:17
  • @SteveSether Would that increase performance? Even so, it would be a platform-dependent solution and I'd rather not rely on that.
    – G_H
    Dec 12 '19 at 16:19
  • /dev/urandom doesn't block. /dev/random does. I'd make a wager there's another random number generator implementation that abstracts away the OS. Maybe bouncycastle? bouncycastle.org Dec 12 '19 at 16:23
  • 1
    Essentially it looks like in Java 8, they realized they were being a bit silly using /dev/random, since it's largely overkill unless you really need "information theoretic randomness", which is what you might care about if you're generating a one-time pad. Dec 12 '19 at 18:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.