KeyGenerator keygen = KeyGenerator.getInstance("Blowfish");
SecureRandom foo = SecureRandom.getInstance("SHA1PRNG");
foo.setSeed("baa".getBytes());
keygen.init(foo);
The problem is that, we found that the key generated in clients is different from that in server. We have tired to print out all steps, and found that the problem is caused by the SecureRandom
, i.e., after foo.setSeed("baa".getBytes());
if we call foo.nextBytes()
, it will give different values.
Therefore, we would like to know whether there is any way to keep both side generate the same value? (Given that the version of Java in both clients and server can not be changed.) Or does any platform independent SecureRandom
method in Java?
Background information: SERVER and CLIENT run in Unix.
I have a desktop running Java 1.8, and I have tested the followings:
Desktop Java 1.8 can encrypt and decrypt the key generated in CLIENT (Java 1.8)
CLIENT (Java 1.8) can not encrypt or decrypt the key generated in SERVER (Java 1.6) and verse versa.
CLIENT has installed Java 1.6 (only for testing) can not encrypt or decrypt the key generated in SERVER (Java 1.6). We guess it is because the /dev/random
or /dev/urandom
has been overwritten to Java 1.8 version. Therefore even the version of Java is the same, they have different behavior.
–
–
–
–
Additionally, SecureRandom
must produce non-deterministic output.
Therefore any seed material passed to a SecureRandom
object must be
unpredictable, and all SecureRandom
output sequences must be
cryptographically strong, as described in RFC 1750: Randomness
Recommendations for Security.
So, not only are you violating the requirements of SecureRandom
by passing a predictable seed, but it is explicitly required that the output of SecureRandom
is unpredictable.
In order to generate a predictable sequence of randomness, use Random
:
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.
But note that: If you use the same seed every time, then the number will always be the same, so you must use the same initial seed, that is shared betwee client and server somehow. This initial seed need to be reset every time the server application is restarted.
The instance of Random
must be shared between calls to the routine, otherwise the same single number will be generated each time:
public static void main(final String[] args) {
IntStream.range(1, 10)
.map(i -> new Random(42).nextInt())
.forEach(System.out::println);
Output:
-1170105035
-1170105035
-1170105035
-1170105035
-1170105035
-1170105035
-1170105035
-1170105035
-1170105035
–
–
–
–
Don't invent your own key deviation functions. Use the functions invented for this.
You don't write what you use as input for your key deviation, but if it's a password you could use a PBE (Password based encryption) Key Spec - something like this:
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "Blowfish");
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.