根据the documentation,SecureRandom 使用的不同算法按优先顺序排列:
- 在大多数 *NIX 系统(包括 macOS)上
- PKCS11(仅在 Solaris 上)
- NativePRNG
- SHA1PRNG
- NativePRNG 阻塞
- NativePRNGNonBlocking
- 在 Windows 系统上
- DRBG
- SHA1PRNG
- Windows-PRNG
既然您询问了 Linux,我将忽略 Windows 实现以及仅在 Solaris 上真正可用的 PKCS11,除非您自己安装它 - 如果您安装了它,您可能不会问这个问题。
根据相同的文档,what these algorithms use 是
SHA1PRNG
目前通过系统属性和 java.security 熵收集设备的组合来完成初始播种。
NativePRNG
nextBytes() 使用 /dev/urandom
generateSeed() 使用 /dev/random
NativePRNGBlocking
nextBytes() 和 generateSeed() 使用 /dev/random
NativePRNGNonBlocking
nextBytes() 和 generateSeed() 使用 /dev/urandom
这意味着如果您使用SecureRandom random = new SecureRandom(),它会在该列表中查找,直到找到一个有效的,通常是 NativePRNG。这意味着它从/dev/random 为自己播种(或者如果您显式生成种子,则使用它),然后使用/dev/urandom 获取下一个字节、整数、双精度、布尔值、what-have-yous。
由于/dev/random 处于阻塞状态(它会阻塞直到熵池中有足够的熵),这可能会影响性能。
一个解决方案是使用类似 hasged 的东西来生成足够的熵,另一个解决方案是使用 /dev/urandom 代替。虽然您可以为整个 jvm 设置它,但更好的解决方案是使用SecureRandom random = SecureRandom.getInstance("NativePRNGNonBlocking") 为SecureRandom 的这个特定实例进行设置。请注意,如果 NativePRNGNonBlocking 不可用,该方法可能会抛出 NoSuchAlgorithmException,因此请准备好回退到默认值。
SecureRandom random;
try {
random = SecureRandom.getInstance("NativePRNGNonBlocking");
} catch (NoSuchAlgorithmException nsae) {
random = new SecureRandom();
}
另请注意,在其他 *nix 系统上,/dev/urandom may behave differently。
/dev/urandom 足够随机吗?
传统观点认为只有/dev/random 是足够随机的。但是,有些声音不同。在"The Right Way to Use SecureRandom" 和"Myths about /dev/urandom" 中,有人认为/dev/urandom/ 一样好。
信息安全堆栈上的用户agree with that。基本上,如果你不得不问,/dev/urandom 很适合你的目的。