Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get deterministic values from SecureRandom?

Tags:

java

random

For benchmarking purposes, I'd like to have a SecureRandom produce deterministic output. Is this possible through the use of a seed (or maybe specification of an algorithm)?

import java.security.SecureRandom;
class TestSecureRandom {
    public static void main(String [] args) {
        SecureRandom rnd = new SecureRandom();
        rnd.setSeed(1);
        System.out.println(rnd.nextInt());
    }
}

For me, the above program produces different values even though the seed is specified.

like image 332
jaynp Avatar asked Dec 07 '14 09:12

jaynp


People also ask

Is SecureRandom deterministic?

Many SecureRandom implementations are in the form of a pseudo-random number generator (PRNG), which means they use a deterministic algorithm to produce a pseudo-random sequence from a true random seed. Other implementations may produce true random numbers, and yet others may use a combination of both techniques.

Is SecureRandom ThreadSafe?

Thread safety. SecureRandom objects are safe for use by multiple concurrent threads. Implementation Requirements: A SecureRandom service provider can advertise that it is thread-safe by setting the service provider attribute "ThreadSafe" to "true" when registering the provider.

Is SecureRandom blocking?

SecureRandom uses /dev/random as its entropy source and thus blocks when the kernel entropy pool runs out of entropy.

What is the difference between random and SecureRandom?

Size: A Random class has only 48 bits whereas SecureRandom can have up to 128 bits. So the chances of repeating in SecureRandom are smaller. Seed Generation: Random uses the system clock as the seed/or to generate the seed. So they can be reproduced easily if the attacker knows the time at which the seed was generated.


3 Answers

In order to override the default seed ,pass PRNG algorithm name like this

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
class TestSecureRandom {
    public static void main(String [] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
        rnd.setSeed("foo".getBytes("us-ascii"));
        System.out.println(rnd.nextInt());
        System.out.println(rnd.nextInt());
    }
}

Ouput

-207444710
-1693504542
like image 101
sol4me Avatar answered Sep 21 '22 10:09

sol4me


Everything is clearly explained in documentation:

Many SecureRandom implementations are in the form of a pseudo-random number generator (PRNG), which means they use a deterministic algorithm to produce a pseudo-random sequence from a true random seed. Other implementations may produce true random numbers, and yet others may use a combination of both techniques.

If you ask about implementation, in Linux it uses /dev/urandom so the result is unpredictable. However, you can force SecureRandom to use another algorithm:

SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");

But for many cases, most reasonable idea is to use some OOP patterns (e.g., jon-skeet's answer).

like image 22
Artur Malinowski Avatar answered Sep 20 '22 10:09

Artur Malinowski


The simplest way of doing this is probably to make most of your code only depend on Random, with an instance being injected (e.g. by passing it into a constructor). That way, for testing purposes you can pass in a simple Random with a fixed seed - but for real runs where security is required, you can pass in an instance of SecureRandom.

like image 38
Jon Skeet Avatar answered Sep 21 '22 10:09

Jon Skeet