关于java:聊聊java的javasecurityegd

41次阅读

共计 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/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 作用

正文完
 0