共计 4347 个字符,预计需要花费 11 分钟才能阅读完成。
序
本文次要钻研一下 java 的 java.security.egd
SunEntries
/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home/src.zip!/sun/security/provider/SunEntries.java
// name of the *System* property, takes precedence over PROP_RNDSOURCE
private final static String PROP_EGD = "java.security.egd";
// name of the *Security* property
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>() {
@Override
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;
}
});
}
这里优先读取
java.security.egd
,如果没有设置则读取$JAVA_HOME/jre/lib/security/java.security
文件中的securerandom.source
配置,默认值为file:/dev/random
SeedGenerator
/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home/src.zip!/sun/security/provider/SeedGenerator.java
// Static initializer to hook in selected or best performing generator
static {String egdSource = SunEntries.getSeedSource();
/*
* Try the URL specifying the source (e.g. file:/dev/random)
*
* The URLs "file:/dev/random" or "file:/dev/urandom" are used to
* indicate the SeedGenerator should use OS support, if available.
*
* On Windows, this causes the MS CryptoAPI seeder to be used.
*
* On Solaris/Linux/MacOS, this is identical to using
* URLSeedGenerator to read from /dev/[u]random
*/
if (egdSource.equals(SunEntries.URL_DEV_RANDOM) ||
egdSource.equals(SunEntries.URL_DEV_URANDOM)) {
try {instance = new NativeSeedGenerator(egdSource);
if (debug != null) {
debug.println("Using operating system seed generator" + egdSource);
}
} 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());
}
}
}
// Fall back to ThreadedSeedGenerator
if (instance == null) {if (debug != null) {debug.println("Using default threaded seed generator");
}
instance = new ThreadedSeedGenerator();}
}
如果是
file:/dev/random
及file:/dev/urandom
则走 NativeSeedGenerator,不是则走 URLSeedGenerator,为空则走 ThreadedSeedGenerator
NativeSeedGenerator
/**
* Native seed generator for Unix systems. Inherit everything from
* URLSeedGenerator.
*
*/
class NativeSeedGenerator extends SeedGenerator.URLSeedGenerator {NativeSeedGenerator(String seedFile) throws IOException {super(seedFile);
}
}
NativeSeedGenerator 继承了 URLSeedGenerator
SecureRandomSpi
NativePRNG
/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home/src.zip!/sun/security/provider/NativePRNG.java
public final class NativePRNG extends SecureRandomSpi {
private static final long serialVersionUID = -6599091113397072932L;
private static final Debug debug = Debug.getInstance("provider");
// name of the pure random file (also used for setSeed())
private static final String NAME_RANDOM = "/dev/random";
// name of the pseudo random file
private static final String NAME_URANDOM = "/dev/urandom";
// which kind of RandomIO object are we creating?
private enum Variant {MIXED, BLOCKING, NONBLOCKING}
// singleton instance or null if not available
private static final RandomIO INSTANCE = initIO(Variant.MIXED);
/**
* Get the System egd source (if defined). We only allow "file:"
* URLs for now. If there is a egd value, parse it.
*
* @return the URL or null if not available.
*/
private static URL getEgdUrl() {
// This will return "" if nothing was set.
String egdSource = SunEntries.getSeedSource();
URL egdUrl;
if (egdSource.length() != 0) {if (debug != null) {debug.println("NativePRNG egdUrl:" + egdSource);
}
try {egdUrl = new URL(egdSource);
if (!egdUrl.getProtocol().equalsIgnoreCase("file")) {return null;}
} catch (MalformedURLException e) {return null;}
} else {egdUrl = null;}
return egdUrl;
}
//......
}
NativePRNG 的 getEgdUrl 则通过 egdSource 来构建 URL
小结
- SunEntries 优先读取
java.security.egd
,如果没有设置则读取$JAVA_HOME/jre/lib/security/java.security
文件中的securerandom.source
配置,默认值为file:/dev/random
- SeedGenerator 判断 egdSource 如果是
file:/dev/random
及file:/dev/urandom
则走 NativeSeedGenerator,不是则走 URLSeedGenerator,为空则走 ThreadedSeedGenerator - 至于
/dev/./urandom
这种示意看起来比拟困惑,翻译过去就是是/dev
当前目录下的unrandom
,其实就是/dev/urandom
,之所以有这种传参次要是晚期 jdk 版本有个 bug,没有给 NativeSeedGenerator 传参,所以通过file:/dev/./urandom
绕过这个 bug
doc
- The java.security.egd JVM Option
- Better Support for High Entropy Random Number Generation
- JEP 123: Configurable Secure Random-Number Generation
- java.security.egd 作用
正文完