2

我正在使用 Java 1.7,并且正如下面的代码所示(在 Ubuntu 中使用 Oracle 的 Java 7 编译器编译)播种java.security.SecureRandom似乎是不必要的,因为代码为两个伪随机序列的起始值生成了两个不同的 BigInteger:

import java.security.SecureRandom;
import java.math.BigInteger;

public class SessionIdTest {

    public static void main (String args[]) {
    long seed = System.currentTimeMillis();
        {
            SecureRandom random = new SecureRandom();
            random.setSeed(seed);
            BigInteger a = new BigInteger(130, random);
            System.out.println(a);
        }
        {
            SecureRandom random = new SecureRandom();
            random.setSeed(seed);
            BigInteger a = new BigInteger(130, random);
            System.out.println(a);
        }
    }
}

那么setSeed的目的是什么?或者,除了种子之外,SecureRandom是否还使用其他一些随机性来源?

4

3 回答 3

2

javadoc 说:

许多 SecureRandom 实现采用伪随机数生成器 (PRNG) 的形式,这意味着它们使用确定性算法从真正的随机种子生成伪随机序列。其他实现可能会产生真正的随机数,而其他实现可能会使用这两种技术的组合。

因此,如文档所述,依靠安全随机数通过播种来生成确定性的值序列并不一定有效。

于 2012-12-24T10:40:04.120 回答
2

JavaDoc 说:

使用给定的long seed. 给定的种子是对现有种子的补充,而不是替代。因此,保证重复调用永远不会减少随机性。

于 2012-12-24T10:40:07.537 回答
1

没有必要SecureRandom通过调用播种 a ,实际上,除非您有一个非常好的熵源并且绝对不是熵源,否则不应该这样做。java.security.SecureRandom#setSeedjava.lang.System#currentTimeMillis

现在,从您的示例中,即使种子相同,它也会产生两个不同的输出。这是我DRBG SecureRandom在 Java 10 的实现中观察到的一种行为,其中产生的两个随机数在一次执行期间会有所不同,但如果程序重新启动则将保持不变:

public class SessionIdTest {

    public static void main (String args[]) throws NoSuchAlgorithmException {
        // Hardcoded seed to evidence the deterministic behavior when the program restarts.
        long seed = 1000;
        {
            SecureRandom random = SecureRandom.getInstance("DRBG");
            random.setSeed(seed);
            BigInteger a = new BigInteger(130, random);
            System.out.println(a);
        }
        {
            SecureRandom random = SecureRandom.getInstance("DRBG");
            random.setSeed(seed);
            BigInteger a = new BigInteger(130, random);
            System.out.println(a);
        }
    }
}

所以前一个总是会产生这样的东西:

724996208419722369188940556616693042555
796664555436785984208644362540465534270

并且一次执行中的不同值的原因在于每次DRBG创建实现时都会更新全局状态。

现在,如果您尝试SHA1PRNG实现,两个随机数将是相同的,并且它们将在程序重新启动时保持不变:

public class SessionIdTest {

    public static void main (String args[]) throws NoSuchAlgorithmException {
        // Hardcoded seed to evidence the deterministic behavior when the program restarts.
        long seed = 1000;
        {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(seed);
            BigInteger a = new BigInteger(130, random);
            System.out.println(a);
        }
        {
            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
            random.setSeed(seed);
            BigInteger a = new BigInteger(130, random);
            System.out.println(a);
        }
    }
}

所以前一个总是会产生这样的东西:

251586625089438840547467272692377284989
251586625089438840547467272692377284989

最后,在这两种情况下,您都可以确认存在基于提供的种子的确定性行为,因此,除非您有非常好的熵源,否则不要SecureRandom手动播种这些 s,并且当前时间不是一个!. 让他们自己播种,这样更安全。

于 2019-03-12T23:39:10.230 回答