// debug 调试代码发现 CryptoUtil.nonce卡住,继续跟踪发现是random.nextInt方法阻塞。
public ScramSession start(String user) {String nonce = CryptoUtil.nonce(nonceLength, secureRandom); // return new ScramSession(scramMechanism,channelBindMethod, serverSupportsChannelBinding,stringPreparation,checkNotNull(user, "user"), nonce);}
public static String nonce(int size, SecureRandom random) {if (size <= 0) {throw new IllegalArgumentException("Size must be positive");}char[] chars = new char[size];int r;for (int i = 0; i < size; ) {r = random.nextInt(MAX_ASCII_PRINTABLE_RANGE - MIN_ASCII_PRINTABLE_RANGE + 1) + MIN_ASCII_PRINTABLE_RANGE;if (r != EXCLUDED_CHAR) {chars[i++] = (char) r;}}return new String(chars);}
// random是调用SecureRandom.getInstanceStrong()方法生成:
private Builder() throws NoSuchAlgorithmException {this.serverAdvertisedMechanisms = Collections.emptyList();this.channelBindMethod = null;this.preferChannelBindingOverAlgorithmStrength = false;this.stringPreparation = StringPreparations.NO_PREPARATION;this.nonceLength = DEFAULT_NONCE_LENGTH;this.secureRandom = SecureRandom.getInstanceStrong();}
在Java中,SecureRandom.getInstanceStrong()
是用于获取安全的随机数生成器(SecureRandom
)的方法。它使用强安全性提供者(Strong Security Provider
)来获取一个实例,这通常是操作系统提供的本地安全实现。虽然这种方法提供了高质量的随机数生成器,但它有时可能导致系统响应变慢的问题。
SecureRandom.getInstanceStrong()
可能需要在获取强安全性提供者的过程中进行耗时的操作,例如系统调用或硬件生成的随机数。这可能导致在某些情况下,特别是在具有低熵(entropy)的系统环境中,调用此方法时会出现较长的延迟。
Linux
内核采用熵来描述数据的随机性,熵(entropy
)是描述系统混乱无序程度的物理量,一个系统的熵越大则说明该系统的有序性越差,即不确定性越大。内核维护了一个熵池用来收集来自设备驱动程序和其它来源的环境噪音。
在Linux
系统中,随机数是通过/dev/random
和/dev/urandom
这两个特殊的设备文件提供的。这些设备文件允许用户和应用程序获取系统的随机数据。这些设备文件利用系统的熵源(entropy source)来生成随机数,其中熵源是系统中的不可预测事件,如硬件中断、鼠标移动、键盘输入等。
以下是/dev/random
和/dev/urandom
的主要区别以及关于它们的一些信息:
/dev/random
:/dev/random
是一个阻塞设备,它会等待足够的熵积累后再提供输出。如果熵不够,读取/dev/random
的操作可能会被阻塞,直到有足够的熵可用。这是为了确保生成的随机数具有更高的质量,因为/dev/random
提供的是真正的随机数。/dev/urandom
:/dev/urandom
是一个非阻塞设备,它会立即提供随机数输出,即使熵源不足。当系统的熵源不足时,/dev/urandom
仍然会生成伪随机数。这样,即使熵源不够,应用程序仍然能够获得随机数,但可能会牺牲一些质量。- 参考: SecureRandom.getInstanceStrong()导致的系统崩溃 - https://zhuanlan.zhihu.com/p/681631220
官方bug: https://github.com/impossibl/pgjdbc-ng/issues/567