Java生成密码安全的伪随机数

示例

Random并且ThreadLocalRandom足够用于日常使用,但是它们有一个大问题:它们基于线性同余生成器,该算法的输出可以很容易地预测。因此,这两个类是适于密码用途(如密钥生成)。

可以java.security.SecureRandom在需要PRNG输出很难预测的情况下使用。预测此类实例创建的随机数很难将其标记为加密安全类。

import java.security.SecureRandom;
import java.util.Arrays;

public class Foo {
    public static void main(String[] args) {
        SecureRandom rng = new SecureRandom();
        byte[] randomBytes = new byte[64];
        rng.nextBytes(randomBytes); // 用随机字节(duh)填充randomBytes
        System.out.println(Arrays.toString(randomBytes));
    }
}

除了具有密码安全性之外,SecureRandom其巨大周期为2 160,而Randoms周期为2 48。但是,它的一个缺点是要比Random其他线性PRNG(例如Mersenne Twister和Xorshift)慢得多。

请注意,SecureRandom实现既依赖于平台,也依赖于提供者。默认值SecureRandom(由的SUN提供者提供sun.security.provider.SecureRandom):

  • 在类Unix系统上,以/dev/random和和或的数据作为种子/dev/urandom。

  • 在Windows上,以CryptGenRandom()CryptoAPI的调用为种子。