I have a HRNG that feeds /dev/random in Debian Wheezy. It's fast, so blocking will not be a problem. Now, in my Java code I want to ensure that I use the entropy in /dev/random and ONLY that entropy. I have no interest in using anything out of /dev/urandom.
I want to force Java's SecureRandom to ONLY get entropy from /dev/random. As I understand the implementation at present, it uses /dev/urandom when getBytes() is called, but /dev/random when generateSeed() is called. I'm at a loss understanding why.
As I understand it, the only reason to read from /dev/urandom is if you favour speed over security. I want the highest quality entropy possible. /dev/urandom will just not do.
So, how do I force SecureRandom to ONLY use /dev/random (supplied by a HRNG) and never touch anything from an inferior PRNG (like /dev/urandom)?
Thanks a mil.
By default, the JVM seeds the SecureRandom class using /dev/random , therefore your Java code can block unexpectedly.
Strictly speaking, /dev/random is not really completely random. /dev/random feeds on hardware sources which are assumed to be unpredictible in some way; then it mixes such data using functions (hash functions, mostly) which are also assumed to be one-way.
/dev/random uses an entropy pool of 4096 bits (512 Bytes) to generate random data and stops when the pool is exhausted until it gets (slowly) refilled. /dev/random is designed for generating cryptographic keys (e.g. SSL, SSH, dm-crypt's LUKS), but it is impractical to use for wiping current HDD capacities: what makes ...
'Urandom' is used where there is constant need of random numbers and its randomness is not much important while 'random' is used where there is a security concern and its randomness should be reliable as it blocks outputting random numbers if entropy is not up to the mark.
This answer assumes you know what you're doing. In other cases, use of /dev/random should be minimized.
/dev/random
acts like a normal file, therefore any program which can read any file can read from /dev/random
. You probably know that cat /dev/random
outputs random data directly from it, and if it does this fast enough, you might in fact want to use it. So, if everything else fails, you'll be always be able to directly read that file...
So, if you look at the source of SecureRandom
, you discover that it uses SecureRandomSpi
for the actual work. It turns out that NativePRNG.Blocking
does what you want:
A NativePRNG-like class that uses /dev/random for both seed and random material. Note that it does not respect the egd properties, since we have no way of knowing what those qualities are. This is very similar to the outer NativePRNG class, minimizing any breakage to the serialization of the existing implementation. Since: 1.8
The problem might be the Since 1.8
, which leaves you with the possibility to backport it to earlier platforms, if you can't use Java 8 yet. The sourcecode is available after all.
So, now let's put this in code:
We have to select the specific implementation to use. To find the exact name, we output all available services with the following line:
for (Provider p: Security.getProviders()) p.getServices().forEach(System.out::println);
We then search for Native
in there, and we find the folllowing entry:
SUN: SecureRandom.NativePRNGBlocking -> sun.security.provider.NativePRNG$Blocking
This means we can instantiate the SecureRandom
object like below to do what you want:
SecureRandom sr = SecureRandom.getInstance("NativePRNGBlocking", "SUN");
A simple test
byte[] b = new byte[10000];
sr.nextBytes(b);
System.out.println(Arrays.toString(b));
takes ages, I had to lower the amount of read bytes. If it works for you, congratulations, you're reading from /dev/random
!
Notice though that this class is in the sun.security.provider
package, which is not guaranteed to be available everywhere. For example, it will probably not work on Android. If this fine, then this solution will work, otherwise you should just directly read it as a file.
Don't read from /dev/random
on Android. Please.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With