当前位置: 首页 > Linux

Linux下随机数SecureRandom块

时间:2023-04-06 23:39:56 Linux

问题背景项目中需要用到随机数,直接使用newRandom()效率太低。为了提高随机性和性能,Sonar推荐您使用子类java.security.SecureRandom来完成。问题程序publicclassTest{publicstaticvoidmain(String[]args)throwsjava.security.NoSuchAlgorithmException{byte[]k=newbyte[20];java.security.SecureRandom.getInstanceStrong().nextBytes(k);系统.out.println(java.util.Arrays.toString(k));}}这段代码在本地环境(Win10+OracleJDK8)和测试环境(CentOS7+OpenJDK1.8)都可以正常输出结果。但是一直阻塞在云服务器(CentOS7+OpenJDK1.8)上。问题分析通过查询资料,发现Linux环境下SecureRandom.getInstanceStrong()方法使用/dev/random生成随机数种子。但是/dev/random是一个阻塞号码生成器。如果没有足够的随机数据,它将永远等待,迫使JVM阻塞。Linux内核使用熵来描述数据的随机性。熵是描述系统混乱程度的物理量。一个系统的熵越大,系统的有序性越差,即不确定性越大。内核维护一个熵池,用于收集来自设备驱动程序和其他来源的环境噪声。简而言之,键盘和鼠标输入以及磁盘活动可以产生所需的随机性或熵。但是在缺少这种活动的服务器上,当系统的熵池数量不足时,就会出现问题,阻塞当前线程。Linux的随机数随机器提供了2种字符设备供用户态进程使用:/dev/random适用于对随机数质量要求较高的请求。当熵池中的数据不足时,读取/dev/random设备将返回小于熵池噪声总量的随机字节。/dev/random生成高度随机的公钥或一次性一密。如果熵池为空,读取/dev/random将阻塞,直到收集到足够的环境噪声。这种设计使/dev/random成为真正的随机数生成器,提供最大可能的随机数据熵。/dev/urandom是一个非阻塞随机数生成器,它重新使用熵池中的数据来生成伪随机数据。这意味着对/dev/urandom的读取操作不会阻塞,但其输出的熵可能小于/dev/random。它可以用作伪随机数生成器,用于生成强度较低的密码,其中随机性对于大多数应用程序来说是可以接受的。解决方案是使用/dev/urandom以非阻塞方式生成随机数,并使用newSecureRandom()而不是SecureRandom.getInstanceStrong()。公共类测试{publicstaticvoidmain(String[]args){byte[]k=newbyte[20];新的java.security.SecureRandom().nextBytes(k);System.out.println(java.util.Arrays.toString(k));}}注:以上代码片段直接使用命令行javacTest.javajavaTest编译运行