public class NonBlockingSecureRandom
extends RandomSource
Non-blocking cryptographically secure random source based on a combination of a time-based
seed generator, reliable external entropy sources, and non-blocking cryptographic functions.
- Time-based seed generator uses nanosecond clock sampled at millisecond resolution according
to thread sleep time which is unpredictable due to wider system processes. This is the same
concept as the ThreadSeedGenerator random seed source used by SecureRandom.
- External entropy sources that are known to be plentiful in the target domain include BLE
MAC address of other devices (usually generated by SecureRandom / UUID), detection time,
and also call time of random function. All are truly unpredictable. Even when there are
no other devices in the vicinity, the call time itself is unpredictable like the time-based
seed generator.
- SHA-256 cryptographic hashing algorithm is known to generate hashes where the individual
bits follow a uniform distribution. This function is used to advance the internal state of
this random source, by hashing a combination of current state and external entropy.
Algorithm and performance characteristics:
- 2048 bit seed entropy collected from thread scheduler timing of 1 millisecond at nanosecond resolution
- Up to 2048 bit external entropy collected from BLE MAC address of target devices and detection time
- 2048 bit internal state updated by SHA-256 of current state and available external entropy
- 2048 bit ephemeral state derived from SHA-256 of XOR(previous state, current state)
- Random bits derived from recursive SHA-256 of XOR(ephemeral state, random output)
- 6298ns/call to nextLong when the internal state is replaced every second.
- Distribution test shows solution offers similar characteristics as BlockingSecureRandomNIST
- BlockingSecureRandomNIST, samples=1000000, sequenceError=0.011800755248335893, valueError=0.0119505
- NonBlockingSecureRandom, samples=1000000, sequenceError=0.011930763568868408, valueError=0.0124595
- BlockingSecureRandom, samples=1000000, sequenceError=0.01340685803891449, valueError=0.0125805
SecureRandom is blocking when it is used on an idle device as entropy is exhausted. The lack
of system activities mean entropy is not replenished at a required rate, thus causing other
subsystems that rely on this mechanism for random data to also block, e.g. BLE MAC address
generation, and halting the app until the device is active again. Experiments have shown even
a single instantiation of SecureRandom on an idle device is sufficient to cause blocking for
this app and wider BLE operations. SecureRandom may also block the app on start up, especially
when the phone was recently booted up. Following numerous investigations and implementations
of a cryptographically secure random source, the evidence suggests SecureRandom should be
avoided completely to prevent blocking.
Please refer to the following paper for a review of entropy sources for SecureRandom
Michaelis K., Meyer C., Schwenk J. (2013) Randomly Failed! The State of Randomness in Current
Java Implementations. In: Dawson E. (eds) Topics in Cryptology – CT-RSA 2013. CT-RSA 2013.
Lecture Notes in Computer Science, vol 7779. Springer, Berlin, Heidelberg.
https://doi.org/10.1007/978-3-642-36095-4_9
This new solution addresses previous vulnerabilities by using
- 2048 bits as internal state
- SHA256 instead of SHA1 for hashing
- Single thread for entropy collection
- Initial entropy collection is blocking
- Reseeding is non-blocking, thus attack on system load cannot compromise internal state
Note: Logging has been disabled by commenting to avoid information leakage, only fault
messages are retained.