Behaviour of SecureRandom

2019-03-27 04:11发布

Even though after following many articles on SecureRandom, I encountered a doubt with the usage of SecureRandom Security API in Java. In the below example .

public class SecureRandomNumber {
public static void main(String[] args) throws NoSuchAlgorithmException {

    TreeSet<Integer> secure = new TreeSet<Integer>();
    TreeSet<Integer> unSecure = new TreeSet<Integer>();
    SecureRandom sr = new SecureRandom();
    byte[] sbuf = sr.generateSeed(8);
    ByteBuffer bb = ByteBuffer.wrap(sbuf);
    long d = bb.getLong();
    sr.setSeed(d);

    Random r = new Random();
    r.setSeed(System.nanoTime());
    for (int k = 0; k < 99999; k++) {
        int i = sr.nextInt();
        if (!secure.add(i)) {
            System.out.println("Repeated Secure Random Number");
        } else {
//              System.out.println("************Unique***********");
        }
        int j = r.nextInt();

        if (!unSecure.add(j)) {
            System.out.println("Repeated UnSecure Random Number");
        }
    }
}

}

When I run this program I do not find any additional benefit of using a SecureRandom as it almost gives the same result.

Can anyone let me know if I am doing the right thing here?

3条回答
小情绪 Triste *
2楼-- · 2019-03-27 04:32

Secure and insecure algorithms will frequently give almost the same result. You can't detect a security flaw in the output. A door with an unpickable lock and a door with a lock that can trivially be picked look pretty much the same and neither will open if you just turn the handle. This is one of the reasons that writing secure code and handling things like encryption and authentication is an area of programming with specialized techniques for design, development, and particularly testing.

查看更多
疯言疯语
3楼-- · 2019-03-27 04:41

You are victim to a common misbelief about random numbers in general: a random sequence doesn't mean that a number cannot be repeated in that sequence. Quite on the contrary, it has to with a high probability. That misbelief is actually used to tell a "random" sequence generated by humans from a real one. A "random" sequence of 0's and 1's generated by a human will probably look like this:

0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, ....

while a real random sequence is not shy of repeating the same number more than twice :) A good example is that statistical tests also look for repetition.

Both kinds of generators have good "statistical properties"

It's also a common misbelief that cryptographically secure random numbers would somehow yield "much more random" values. Their statistical probabilities will probably be pretty much alike and both will perform really well in those standard statistical tests.

Where to use which

So it actually depends on what you want to do whether your choice should be a PRNG or a cryptographically secure PRNG (CSPRNG). "Normal" PRNGs are perfectly fine for simulation purposes such as Monte-Carlo methods etc. The additional benefit of a CSPRNG will give you is that of non-predictability. Because the CSPRNG can "do more" chances are high that its performance will also be worse than that of a vanilla PRNG.

It can be shown that the concept of a "secure" PRNG is tightly coupled with the ability to predict the next bit of its output. For a CSPRNG, predicting the next bit of its output at any time is computationally infeasible. This only holds if you treat its seed value as a secret, of course. Once anyone finds out the seed, the whole thing becomes easily predictable - just recompute the values already generated by the CSPRNG's algorithm and then compute the next value. It can further be shown that being immune to "next-bit prediction" actually implies that there's no statistical test whatsoever that could distinguish the distribution of the CSPRNG from that of a real random uniform distribution. So there's another difference between PRNG and CSPRNG: While a good PRNG will perform well in many statistical tests, a CSPRNG is guaranteed to perform well in all tests.

The rule of thumb where to use which is that

  • You use the CSPRNG in a "hostile" environment where you don't want externals to be able to guess sensitive information (session IDs, online poker where real money is won/lost, ....)
  • And the PRNG in a benevolent environment where you just require good statistical properties but don't care about predictability (Monte-Carlo simulations, single player poker vs. computer, computer games in general) - i.e. no money can be won or lives will be lost should somebody be able to predict those random numbers successfully.
查看更多
迷人小祖宗
4楼-- · 2019-03-27 04:41

SecureRandom doesn't ensure unique random numbers each time. It just ensures that given the previous numbers, you cannot predict the next random number. So, basically, you are looking for the wrong answer.

Lets use the example of dice. Using secure random is like using a normal unloaded dice. Every dice roll is independent of the previous dice roll. A not secure random uses the previous dice roll to determine the next result. (So if you know the previous roll was a six, you can predict the next dice roll).

So you basically have to determine if it is a problem for your application if users/hackers/administrators/etc could predict which number comes up if given the previous list of random numbers. (In most cases this will be a problem). If you just want to use random numbers to select a random thing to show in a webpage, normal random is fine. If you want to use random number for security, or games, or trading it is best to use SecureRandom.

I'm not sure, but I think using SecureRandom has a very minor overhead increase. So random is slightly faster. But in most cases this increase in speed is not worth the potential problems laster when you people abuse the insecurity of not secure random number generator.

查看更多
登录 后发表回答