java - 如果 Jetty 的 key store 中有多个证书,它如何选择?

标签 java ssl certificate jetty

我们的系统中有一些代码可以自动将自签名证书生成到 keystore 中,然后由 Jetty 使用。如果给定主机的 key 已经存在,则什么也不会发生,但如果不存在,我们将生成一个新 key ,如下所示:

public void generateKey(String commonName) {
    X500Name x500Name = new X500Name("CN=" + commonName);
    CertAndKeyGen keyPair = new CertAndKeyGen("DSA", "SHA1withDSA");
    keyPair.generate(1024);
    PrivateKey privateKey = keyPair.getPrivateKey();
    X509Certificate certificate = keyPair.getSelfCertificate(x500Name, 20*365*24*60*60);
    Certificate[] chain = { certificate };
    keyStore.setEntry(commonName, privateKey, "secret".toCharArray(), chain);
}

只要 keystore 中只有一个 key 和证书,这一切都可以正常工作。一旦你有多个 key ,当你尝试连接时会发生奇怪的事情:

java.io.IOException: HTTPS hostname wrong:  should be <127.0.0.1>

这是一个相当神秘的错误,但我最终设法通过编写连接到服务器并断言证书上的 CN 与主机名匹配的单元测试来追踪它。我的发现非常有趣 - Jetty 似乎可以任意选择向客户出示哪个证书,但方式是一致的。

例如:

  • 如果“CN=localhost”和“CN=cheese.mydomain”在 keystore 中,它总是选择“CN=cheese.mydomain”。
  • 如果“CN=127.0.0.1”和“CN=cheese.mydomain”在 keystore 中,它总是选择“CN=cheese.mydomain”。
  • 如果“CN=192.168.222.100”(cheese.mydomain) 和“CN=cheese.mydomain”在 keystore 中,它总是选择“CN=192.168.222.100”。

我编写了一些代码来循环遍历商店中的证书以将它们打印出来,但发现它并没有始终如一地选择第一个证书或类似的任何琐碎的事情。

那么它到底使用什么标准呢?最初我认为 localhost 很特别,但第三个例子让我完全困惑。

我认为这是由 KeyManagerFactory 以某种方式决定的,在我的例子中是 SunX509。

最佳答案

这确实最终由 KeyManager 决定(通常从 KeyManagerFactory 获得)。

一个 keystore 可以有许多证书存储在不同的别名下。如果没有通过 certAlias in the Jetty configuration 显式配置别名,SunX509 实现将选择它找到的第一个别名,其中有一个私钥和所选密码套件的正确类型的 key (通常是 RSA,但在您的情况下可能是 DSA)。如果您查看 Sun provider implementation,选择逻辑还有更多内容,但您不应该真正依赖一般的顺序,而只是别名。

你当然可以给 Jetty 你自己的 SSLContext 和你自己的 X509KeyManager选择别名。您必须实现:

 chooseServerAlias(String keyType, Principal[] issuers, Socket socket)

不幸的是,除了 keyTypeissuers 之外,您只能通过 socket 本身做出决定。充其量,您在那里获得的有用信息是本地 IP 地址和远程 IP 地址。

除非您的服务器在同一端口上监听多个 IP 地址,否则您将始终获得相同的本地 IP 地址。 (显然,在这里,您至少有两个:127.0.0.1192.168.222.100,但我怀疑除了您自己的测试之外,您对 localhost 并不真正感兴趣。 ) 您需要服务器端的服务器名称指示 (SNI) 支持才能根据请求的主机名(由支持它的客户端)做出决定。不幸的是,SNI was only introduced in Java 7, but only on the client side .

您将在这里面临的另一个问题是 Java clients will complain about IP addresses in the Subject DN's CN .有些浏览器可以容忍这种情况,但这不符合 HTTPS 规范 (RFC 2818)。 IP 地址必须是 IP 地址类型的主题备用名称条目。

关于java - 如果 Jetty 的 key store 中有多个证书,它如何选择?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10425306/

相关文章:

java - 创建 bean sessionFactory 时出错

java - Spring Security、表单登录和并发 session

ios - 卡在为 Bluemix 推送创建 .p12 推送证书文件

ssl - 在 JBoss 上安装 SSL 证书

wcf - 客户端身份验证方案 'Anonymous' 禁止 HTTP 请求

java - 可选择的多播套接字(1.7 之前)

Java - 在悬停时在 JButton 中添加和删除带下划线的文本

apache - 如何阻止 Chrome 重定向到 HTTPS?

IOS生产证书,我应该向其他方提供什么才能使用相同的证书?

ssl - 802.1ar 安全设备身份证书