序
本文主要研究一下java的java.security.egd
SunEntries
/Library/Java/JavaVirtualMachines/temurin-8.jdk/Contents/Home/src.zip!/sun/security/provider/SunEntries.java
代码语言:javascript复制 // 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
代码语言:javascript复制 // 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
代码语言:javascript复制/**
* 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
代码语言:javascript复制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 作用