TJ-*_*TJ- 5 java random tomcat aes strace
我正在尝试调试部署在Tomcat上的应用程序提供的一些慢响应.现在,我侧重于SecureRandom和/dev/random(其他一些可能的原因进行了调查和排除).模式如下:
服务调用涉及加密和解密(AES/ECB/PKCS5Padding).
SecureRandom init/repopulating是否可能导致这种情况发生?
(虽然有一个用catalina.log写的日志说"Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [28,760] milliseconds.")
此外,为了检查是否/dev/random或/dev/urandom正在使用,我到测试使用的这个问题.令我惊讶的是,我没有看到其中任何一个的读取,不像链接问题中发生的那样.这些是strace日志中的最后几行:
3561  lstat("/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/jsse.jar", {st_mode=S_IFREG|0644, st_size=258525, ...}) = 0
3561  open("/usr/lib/jvm/java-1.6.0-openjdk-1.6.0.0.x86_64/jre/lib/jsse.jar", O_RDONLY) = 6
3561  stat("/dev/random", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 8), ...}) = 0
3561  stat("/dev/urandom", {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 9), ...}) = 0
3561  open("/dev/random", O_RDONLY)     = 7
3561  open("/dev/urandom", O_RDONLY)    = 8
3561  unlink("/tmp/hsperfdata_xxxx/3560") = 0
那么什么用于播种SecureRandom?
fyi,java -version
java version "1.6.0_32"
OpenJDK Runtime Environment (IcedTea6 1.13.4) (rhel-7.1.13.4.el6_5-x86_64)
OpenJDK 64-Bit Server VM (build 23.25-b01, mixed mode)
我无法检查您的 OpenJDK 具体版本,但我可以检查jdk6-b33。
SecureRandom使用SeedGenerator获取种子字节
public byte[] engineGenerateSeed(int numBytes) {
    byte[] b = new byte[numBytes];
    SeedGenerator.generateSeed(b);
    return b;
}
seedSourceSeedGenerator从SunEntries获取(字符串)
String egdSource = SunEntries.getSeedSource();
SunEntries首先尝试从系统属性中获取源,如果未找到,则尝试从属性文件中java.security.egd获取属性,如果未找到属性,则返回空字符串。securerandom.sourcejava.security
// 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>() {
        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此值以初始化实例
// Static instance is created at link time
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 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 URL file:/dev/random or file:/dev/urandom is used to indicate
    // the SeedGenerator using OS support, if available.
    // On Windows, the causes MS CryptoAPI to be used.
    // On Solaris and Linux, this is the identical to using
    // URLSeedGenerator to read from /dev/random
    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());
        }
    }
    // Fall back to ThreadedSeedGenerator
    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 上尝试使用CryptoAPILinux 上的本机类,只是扩展了SeedGenerator.URLSeedGenerator
package sun.security.provider;
import java.io.IOException;
/**
 * Native seed generator for Unix systems. Inherit everything from
 * URLSeedGenerator.
 *
 */
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
希望这可以帮助。
| 归档时间: | 
 | 
| 查看次数: | 4291 次 | 
| 最近记录: |