The Java SecureRandom Class – Java的SecureRandom类

最后修改: 2019年 7月 6日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

In this short tutorial, we’ll learn about java.security.SecureRandom, a class that provides a cryptographically strong random number generator.

在这个简短的教程中,我们将学习java.security.SecureRandom,一个提供密码学上强大的随机数发生器的类。

2. Comparison to java.util.Random

2.与java.util.Random比较

Standard JDK implementations of java.util.Random use a Linear Congruential Generator (LCG) algorithm for providing random numbers. The problem with this algorithm is that it’s not cryptographically strong. In other words, the generated values are much more predictable, therefore attackers could use it to compromise our system.

java.util.Random的标准JDK实现使用Linear Congruential Generator(LCG)算法来提供随机数。这种算法的问题是,它在密码学上并不强大。换句话说,生成的值更容易预测,因此攻击者可以利用它来破坏我们的系统。

To overcome this issue, we should use java.security.SecureRandom in any security decisions. It produces cryptographically strong random values by using a cryptographically strong pseudo-random number generator (CSPRNG).

为了克服这个问题,我们应该在任何安全决策中使用java.security.SecureRandom。它通过使用加密强的伪随机数生成器CSPRNG)产生加密强的随机值。

For a better understanding of the difference between LCG and CSPRNG, please look at the below chart presenting a distribution of values for both algorithms:

为了更好地理解LCG和CSPRNG的区别,请看下面的图表,呈现了两种算法的数值分布。

secure random algorithms

 

3. Generating Random Values

3.生成随机值

The most common way of using SecureRandom is to generate int, long, float, double or boolean values:

使用SecureRandom的最常见方式是生成intlongfloatdoubleboolean

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

For generating int values we can pass an upper bound as a parameter:

对于生成int值,我们可以传递一个上限作为参数。

int randomInt = secureRandom.nextInt(upperBound);

In addition, we can generate a stream of values for int, double and long:

此外,我们可以为int,doublelong生成一个值流。

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

For all streams we can explicitly set the stream size:

对于所有的流,我们可以明确地设置流的大小。

IntStream intStream = secureRandom.ints(streamSize);

and the origin (inclusive) and bound (exclusive) values as well:

以及原点(包括)和边界(不包括)的值也是如此。

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

We can also generate a sequence of random bytes. The nextBytes() function takes user-supplied byte array and fills it with random bytes:

我们还可以生成一个随机字节的序列nextBytes()函数接收用户提供的byte数组,并以随机字节填充它。

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

4. Choosing an Algorithm

4.选择一个算法

By default, SecureRandom uses the SHA1PRNG algorithm to generate random values. We can explicitly make it use another algorithm by invoking the getInstance() method:

默认情况下,SecureRandom使用SHA1PRNG算法来生成随机值。我们可以通过调用getInstance()方法明确地让它使用另一种算法。

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

Creating SecureRandom with the new operator is equivalent to SecureRandom.getInstance(“SHA1PRNG”).

new操作符创建SecureRandom相当于SecureRandom.getInstance(“SHA1PRNG”)

All random number generators available in Java can be found on the official docs page.

所有Java中可用的随机数生成器都可以在官方文档页面上找到

5. Seeds

5.种子

Every instance of SecureRandom is created with an initial seed. It works as a base for providing random values and changes every time we generate a new value.

每个SecureRandom的实例都是用一个初始种子创建的。它作为提供随机值的基础,在我们每次生成新值时都会发生变化。

Using the new operator or calling SecureRandom.getInstance() will get the default seed from /dev/urandom.

使用new操作符或调用SecureRandom.getInstance()/dev/urandom获得默认种子。

We can change the seed by passing it as a constructor parameter:

我们可以通过将种子作为构造函数参数传递来改变种子。

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

or by invoking a setter method on the already created object:

或在已经创建的对象上调用一个setter方法。

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

Remember that if we create two instances of SecureRandom with the same seed, and the same sequence of method calls is made for each, they will generate and return identical sequences of numbers.

请记住,如果我们用相同的种子创建两个SecureRandom的实例,并且为每个实例进行相同的方法调用序列,它们将生成并返回相同的数字序列。

6. Conclusion

6.结语

In this tutorial, we’ve learned how the SecureRandom works and how to use it for generating random values.

在本教程中,我们已经了解了SecureRandom的工作原理以及如何使用它来生成随机值。

As always, all code presented in this tutorial can be found over on GitHub.

一如既往,本教程中介绍的所有代码都可以在GitHub上找到