前面的几篇文章,介绍了随机数的几种生成方式,那么什么是伪随机数呢?
所谓伪随机数,是指只要给定⼀个初始的种⼦,产⽣的随机数序列是完全⼀样的。
for (int i = 0; i < 10; i++) {
Random random = new Random(123);
int randomValue = random.nextInt(10);
System.out.println(randomValue);
}
当我们初始化Random不给定种子的时候,会默认给定当前的时间作为种子。
/**
* Creates a new random number generator. This constructor sets
* the seed of the random number generator to a value very likely
* to be distinct from any other invocation of this constructor.
*/
public Random() {
this(seedUniquifier() ^ System.nanoTime());
}
跟踪
* @return the current value of the running Java Virtual Machine's
* high-resolution time source, in nanoseconds
* @since 1.5
*/
public static native long nanoTime();
那么,什么是真随机数呢?
真正的真随机数只能通过量⼦⼒学原理来获取,⽽我们想要的是⼀个不可预测的安全的随机
数,SecureRandom就是⽤来创建安全的随机数的:
SecureRandom sr = new SecureRandom();
System.out.println(sr.nextInt(100));
SecureRandom⽆法指定种⼦,它使⽤RNG(random number generator)算法。JDK的SecureRandom实际上有多种不同的底层实现,有的使⽤安全随机种⼦加上伪随机数算法来产⽣安全的随机数,有的使⽤真正的随机数⽣成器。
实际使⽤的时候,可以优先获取⾼强度的安全随机数⽣成器,如果没有提供,再使⽤普通等级的安全随机数⽣成器:
import java.util.Arrays;
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
public class Main {
public static void main(String[] args) {
SecureRandom sr = null;
try {
// 获取⾼强度安全随机数⽣成器
sr = SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
// 获取普通的安全随机数⽣成器
sr = new SecureRandom();
}
}
SecureRandom的安全性是通过操作系统提供的安全的随机种⼦来⽣成随机数。
这个种⼦是通过CPU的热噪声、读写磁盘的字节、⽹络流量等各种随机事件产⽣的“熵”。
在密码学中,安全的随机数⾮常重要。如果使⽤不安全的伪随机数,所有加密体系都将被攻破。
因此,时刻牢记必须使⽤SecureRandom来产⽣安全的随机数。