generic, reusable cryptography services
RandomStringGenerator
.generate() - generates a random String
Implementations
RandomStringGeneratorImpl
constructors
RandomStringGeneratorImpl(Integer length) - length is the desired length of the generated Strings
about
This implementation generates cryptographically secure random Strings suitable for use as access tokens (assuming sufficient length).
The generated Strings are alphanumeric, using both upper and lower case letters from the English alphabet.
Each String is generated using a new Random instance, which is only used to generate one String and then never reused.
A Random instance by does not not generate cryptographically secure sequences. With sufficient samples an attacker can work out the seed and predict future values, and by default an instance is seeded with the current System timestamp, which puts it in a tractable range for brute force attacks, too.
This implementation mitigates against these weaknesses in two ways.
Firstly, because each Random is used only once to generate one String, analysing one String and cracking the Random seed used to generate it does not give you any information you can use to guess other Strings generated in the past or future.
Secondly, arbitrary Strings cannot be guessed using brute force timing-based attacks because each Random instance is seeded with a real random number composed by adding together a number generated by a SecureRandom instance (which draws randomness from the underlying OS and is cryptographically secure) and the number of calls to .generate() which have so far occurred (this is more of a why-not-it's-cheap source of noise to the already extremely secure seed).
Why not just use SecureRandom to pick all the random characters, instead of seeding a Random instance with it and using that? Good question! There's a performanceTest() method in the test class which showed me a 25x performance increase doing the latter rather than the former. If you're going to be using this a lot, for example regenerating access tokens on every api call, or something, then that really matters (imagine running a single server rather than a cluster of 25 at scale :-), and if my understanding is correct, there's no practical loss of security by doing it.
Because of the use of SecureRandom, a RandomStringGeneratorImpl instance is expensive to initialise, so it is preferable (and perfectly secure) to construct an instance once and reuse it as much as possible.
Unit tests
There is an abstract base unit test class for generate() that new implementations can piggy-back on for zero effort testability - only limitation is it assumes an implementation with a constructor taking an Integer length argument, for the length of string to produce.
It tests
-
Strings of the correct length are produced
-
Strings are sufficiently random - i.e. no duplicates are produced over a large-enough sample size (configurable in the contructor depending on your use-case).
-
Performance test - how quickly are 1 million Strings of length 128 produced. This is useful for tweaking the performance of your implementation, once you know it works.