问题
I have a quandary on my hands. I created an AES service to encrypt/decrypt sensitive information. The AES key is randomly generated using java's SecureRandom
. I have a protected file that stores the seed and upon calling the service the seed is populated into the Secure Random class.
To make sure it works I have the following logic:
private boolean secureRandom(final String seed) {
SecureRandom sr1 = new SecureRandom(seed.getBytes(UTF8_CHARSET));
SecureRandom sr2 = new SecureRandom(seed.getBytes(UTF8_CHARSET));
//Two secure random with the same seed should generate the same results
boolean secureRandomWorks = sr1.nextLong() == sr2.nextLong();
if (!secureRandomWorks) {
System.err.println("Secure random not supported. Defaulting to old key");
}
return secureRandomWorks;
}
The idea here is I should be able to create two secure random objects with the same seed and they should both return the same value upon the call to nextLong()
When I deploy my application on a windows machine this works fine, but when I deploy it on a RHEL 7 machine I get my error.
I was under the impression that as long as the seed is the same, both instances will always produce the same output. This seems to be the case on windows, but not when I tested it on RHEL 7 this doesn't seem to be the case.
I created this simple test to see verify:
SecureRandom sr1 = new SecureRandom("encryptionKey".getBytes("UTF-8"));
SecureRandom sr2 = new SecureRandom("encryptionKey".getBytes("UTF-8"));
for (int i = 0; i < 1000; i++) {
System.out.println(sr1.nextLong() == sr2.nextLong());
}
And on windows every output was true while on RHEL 7 this was false.
Any idea's suggestions on what might be causing RHEL 7 to ignore the seed?
回答1:
I don't find any documentation that prohibits the behavior that you observe on RHEL 7.
The JavaDoc for java.util.Random explicitly states
If two instances of Random are created with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers
The JavaDoc for java.security.SecureRandom contains no similar statement.
On the contrary, it mentions (in the documentation for the setSeed()
method)
Reseeds this random object. The given seed supplements, rather than replaces, the existing seed. Thus, repeated calls are guaranteed never to reduce randomness.
回答2:
Turns out that RHEL 7 (and Linux machines in general) uses a different algorithm by default than windows. Linux uses NativePRNG
while Windows uses SHA1PRNG
.
Linux utilizes the built in /dev/random
or /dev/urandom
with the use of NativePRNG
.
With this in mind I was able to change how I initialize the SecureRandom object
private static final String ALGORITHM = "SHA1PRNG";
private static final String PROVIDER = "SUN";
private SecureRandom getSecureRandom(String seed) throws NoSuchAlgorithmException, NoSuchProviderException {
SecureRandom sr = SecureRandom.getInstance(ALGORITHM, PROVIDER);
sr.setSeed(seed.getBytes(UTF8_CHARSET));
return sr;
}
From the documentation getInstance
does not seed the object thus it does as I need.
The returned SecureRandom object has not been seeded. To seed the returned object, call the setSeed method. If setSeed is not called, the first call to nextBytes will force the SecureRandom object to seed itself. This self-seeding will not occur if setSeed was previously called.
Now it is forced to use what I need and I shouldn't have an issue with RHEL 7.
来源:https://stackoverflow.com/questions/50107982/rhe-7-not-respecting-java-secure-random-seed