本文次要钻研一下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/randomfile:/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/randomfile:/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 作用