我无法检查您的OpenJDK具体版本,但我可以检查
jdk6-b33。
SecureRandom使用
SeedGenerator获取种子字节。
public byte[] engineGenerateSeed(int numBytes) {
byte[] b = new byte[numBytes];
SeedGenerator.generateSeed(b);
return b;
}
SeedGenerator从
SunEntries获取
seedSource
(字符串)。
String egdSource = SunEntries.getSeedSource()
SunEntries
首先尝试从系统属性 java.security.egd
中获取源,如果找不到,则尝试从 java.security
属性文件中获取属性 securerandom.source
,如果未找到该属性,则返回空字符串。
private final static String PROP_EGD = "java.security.egd";
private final static String PROP_RNDSOURCE = "securerandom.source";
final static String URL_DEV_RANDOM = "file:/dev/random";
final static String URL_DEV_URANDOM = "file:/dev/urandom";
private static final String seedSource;
static {
seedSource = AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
String egdSource = System.getProperty(PROP_EGD, "");
if (egdSource.length() != 0) {
return egdSource;
}
egdSource = Security.getProperty(PROP_RNDSOURCE);
if (egdSource == null) {
return "";
}
return egdSource;
}
});
}
SeedGenerator
会检查这个值以初始化实例
private static SeedGenerator instance;
private static final Debug debug = Debug.getInstance("provider");
final static String URL_DEV_RANDOM = SunEntries.URL_DEV_RANDOM;
final static String URL_DEV_URANDOM = SunEntries.URL_DEV_URANDOM;
static {
String egdSource = SunEntries.getSeedSource();
if (egdSource.equals(URL_DEV_RANDOM) || egdSource.equals(URL_DEV_URANDOM)) {
try {
instance = new NativeSeedGenerator();
if (debug != null) {
debug.println("Using operating system seed generator");
}
} catch (IOException e) {
if (debug != null) {
debug.println("Failed to use operating system seed "
+ "generator: " + e.toString());
}
}
} else if (egdSource.length() != 0) {
try {
instance = new URLSeedGenerator(egdSource);
if (debug != null) {
debug.println("Using URL seed generator reading from "
+ egdSource);
}
} catch (IOException e) {
if (debug != null)
debug.println("Failed to create seed generator with "
+ egdSource + ": " + e.toString());
}
}
if (instance == null) {
if (debug != null) {
debug.println("Using default threaded seed generator");
}
instance = new ThreadedSeedGenerator();
}
}
如果源代码是
final static String URL_DEV_RANDOM = "file:/dev/random";
或者
final static String URL_DEV_URANDOM = "file:/dev/urandom"
使用 NativeSeedGenerator
,在 Windows 上尝试使用本机的 CryptoAPI
,在 Linux 上该类只是扩展了 SeedGenerator.URLSeedGenerator
package sun.security.provider;
import java.io.IOException;
class NativeSeedGenerator extends SeedGenerator.URLSeedGenerator {
NativeSeedGenerator() throws IOException {
super();
}
}
并调用超类构造函数,默认加载/dev/random
URLSeedGenerator() throws IOException {
this(SeedGenerator.URL_DEV_RANDOM);
}
因此,默认情况下,OpenJDK使用/dev/random
,直到您在系统属性java.security.egd
或安全属性文件的securerandom.source
属性中设置其他值。
如果您想使用strace
查看读取结果,可以更改命令行并添加trace=open,read
表达式。
sudo strace -o a.strace -f -e trace=open,read java class
你可以看到类似这样的东西(我使用Oracle JDK 6进行测试)
13225 open("/dev/random", O_RDONLY) = 8
13225 read(8, "@", 1) = 1
13225 read(3, "PK\3\4\n\0\0\0\0\0RyzB\36\320\267\325u\4\0\0u\4\0\0 \0\0\0", 30) = 30
....
....
Tomcat Wiki中关于更快启动的部分建议在启动过程中遇到延迟时使用非阻塞熵源,如/dev/urandom。
更多信息请参见:
https://wiki.apache.org/tomcat/HowTo/FasterStartUp#Entropy_Source 希望这可以帮助你。
new SecureRandom
创建一个新的随机生成器,然后从中读取一些字节,看看是否从urandom
中读取。确保你针对相同的 Java 运行时,并检查java.security.egd
属性是否未使用java -D
设置为 Tomcat。 - Maarten Bodewesjre/lib/security/java.security
这个文件,看一下securerandom.source
是怎么定义的? - Maarten Bodewes/dev/./urandom
,看看会发生什么吗? - Maarten Bodewes