1. 简介

在本篇简明教程中,我们将深入了解 java.security.SecureRandom 类。这是一个用于生成密码学强度的随机数生成器(Cryptographically Strong Random Number Generator)的类。

2. 与 java.util.Random 的对比

标准 JDK 中的 java.util.Random 类通常使用的是 线性同余生成器(LCG)算法。这个算法虽然效率高,但并不适合用于安全场景,因为其生成的随机数序列是高度可预测的,攻击者可能利用这一特性入侵系统。

SecureRandom 使用的是密码学安全伪随机数生成器(Cryptographically Secure Pseudorandom Number Generator, CSPRNG)算法,生成的随机数具有更高的不可预测性,适合用于安全相关的场景,如生成密钥、令牌、盐值等。

下图展示了 LCG 与 CSPRNG 在数值分布上的差异:

secure random algorithms

3. 生成随机值

使用 SecureRandom 可以简单高效地生成各种基本类型的随机值,包括 intlongfloatdoubleboolean

int randomInt = secureRandom.nextInt();
long randomLong = secureRandom.nextLong();
float randomFloat = secureRandom.nextFloat();
double randomDouble = secureRandom.nextDouble();
boolean randomBoolean = secureRandom.nextBoolean();

如果想生成指定范围内的整数,可以传入一个上限值:

int randomInt = secureRandom.nextInt(upperBound);

此外,还可以生成随机值的流:

IntStream randomIntStream = secureRandom.ints();
LongStream randomLongStream = secureRandom.longs();
DoubleStream randomDoubleStream = secureRandom.doubles();

你也可以指定流的大小:

IntStream intStream = secureRandom.ints(streamSize);

或者指定流的起始值和边界值(包含起始值,不包含边界值):

IntStream intStream = secureRandom.ints(streamSize, originValue, boundValue);

还可以生成随机字节数组:

byte[] values = new byte[124];
secureRandom.nextBytes(values);

4. 选择算法

默认情况下,SecureRandom 使用的是 SHA1PRNG 算法来生成随机数。你也可以通过调用 getInstance() 方法显式指定其他算法:

SecureRandom secureRandom = SecureRandom.getInstance("NativePRNG");

使用 new SecureRandom() 相当于调用 SecureRandom.getInstance("SHA1PRNG")

Java 中支持的随机数生成算法可以参考 官方文档

5. 种子(Seed)

每个 SecureRandom 实例在初始化时都会带有一个种子(seed)。这个种子是生成随机值的基础,并且每次生成新值时都会被重新混合。

使用 new 关键字或调用 SecureRandom.getInstance() 会从 /dev/urandom 获取默认种子(在类 Unix 系统中)。

你可以通过构造函数传入自定义种子:

byte[] seed = getSecureRandomSeed();
SecureRandom secureRandom = new SecureRandom(seed);

或者通过 setSeed() 方法设置种子:

byte[] seed = getSecureRandomSeed();
secureRandom.setSeed(seed);

⚠️ 注意:设置种子并不能保证生成的随机数序列是确定的,因为 SecureRandom 会将你提供的种子与多个熵源混合,以增强不可预测性。与普通伪随机数生成器不同,它的设计初衷就是即使设置了种子,也保持非确定性行为,从而确保安全性。

6. 小结

本文我们介绍了 Java 中 SecureRandom 的基本使用方法,包括:

✅ 如何生成各种类型的随机值
✅ 如何选择不同的算法
✅ 种子的作用以及设置方式
✅ 为什么 SecureRandom 更适合用于安全场景

如果你的应用涉及密码学操作、安全认证、令牌生成等场景,**务必使用 SecureRandom 而不是 Random**。

完整的示例代码可以在 GitHub 仓库 中找到。


原始标题:The Java SecureRandom Class | Baeldung