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)) .limit(keyLength) ... // 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?