7

是否可以使用 SSL 连接到客户端只有根证书但服务器同时具有根证书和中间证书的站点?

我正在尝试使用 HttpUrlConnection 与包含我的根的 TrustManager 进行连接,但出现通常的握手错误:

javax.net.ssl.SSLHandshakeException:
  sun.security.validator.ValidatorException:
  Certificate chaining error
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)

我知道一般的解决方案是安装中间证书,但我想避免不断地一次性获得供应商 X 的新中间证书。

我熟悉使用接受所有内容的 TrustManager,但这不是一种选择。

4

4 回答 4

16

是否可以使用 SSL 连接到客户端只有根证书但服务器同时具有根证书和中间证书的站点?

这不仅是可能的,而且实际上是 TLS 工作的常用方式:

  1. TLS 客户端只有根证书。Java——至少是 Oracle JVM——从lib/security/cacertsJRE 安装目录中读取它们。浏览器要么有自己的内部列表,要么使用操作系统提供的列表。
  2. 当客户端启动 TLS 连接时,服务器应该发回自己的证书以及任何中间证书(如果它使用任何中间证书) - 这个列表称为证书链。对于当前版本 1.2。TLS 的这在RFC 5246 的第 7.4.2 节中指定(请参阅下面的报价)。
  3. 客户端接收这些证书,并验证签名,从服务器证书到它知道的根证书之一。这称为认证路径构建,并在RFC 4158中进行了描述。
  4. 如果客户端可以构建有效的证书路径,它会继续进行连接设置。否则,它会以错误消息中止 - 类似于可怕的“此连接不受信任”错误。

我知道一般的解决方案是安装中间证书

不,实际上不是,如上所述,服务器应该自动发送所有中间证书。

然而:

服务器上一个相当常见的配置错误是未在服务器上安装所有中间证书。在这种情况下,服务器将在连接设置期间发送不完整的证书链。然后客户端将无法建立有效的认证路径,并将中止连接。

一些并发症会使这个问题难以诊断:

  • 一些客户端(尤其是浏览器)可能仍然可以成功连接,因为它们有丢失的中间证书的缓存副本。
  • 大多数客户端不会或无法区分丢失的中间证书(在服务器发送的链中)、丢失的根证书(在他们自己的列表中)和自签名证书,因此您必须自己弄清楚什么问题实际上是。

诊断这些问题的有用工具:

  • OpenSSL 的命令行客户端可以显示服务器发送的证书链:openssl s_client -showcerts -connect google.com:443
  • Qualys 的SSL 服务器测试将列出证书链以及任何验证错误

RFC 5246 第 7.4.2 节的相关引用:

7.4.2. 服务器证书

何时发送此消息:

每当商定的密钥交换方法使用证书进行身份验证时,服务器必须发送一个证书消息(这包括本文档中定义的所有密钥交换方法,除了 DH_anon)。此消息将始终紧跟在 ServerHello 消息之后。

此消息的含义:

此消息将服务器的证书链传送给客户端。

[...]

此消息的结构:

[...]

证书列表

这是证书的序列(链)。发件人的证书必须在列表中排在第一位。后面的每个证书必须直接证明它前面的证书。因为证书验证要求根密钥是独立分发的,所以可以从链中省略指定根证书颁发机构的自签名证书,假设远程端必须已经拥有它才能在任何情况下验证它。

于 2015-04-10T09:22:58.877 回答
7

服务器应该在消息中发送整个证书链,包括中间证书Certificate。客户端将检查整个链并找到它信任的根证书。所以你所描述的应该有效。

当然,有可能(错误)配置服务器不发送整个链 - 在这种情况下,客户端的检查可能会失败。

于 2012-04-12T23:50:14.700 回答
3

本答案所述:

使用 Oracle JRE,您可以启用具有 Java 系统属性的中间证书的自动下载-Dcom.sun.security.enableAIAcaIssuers=true

为此,服务器的证书必须提供中间证书(证书的颁发者)的 URI。

于 2018-09-10T01:22:17.403 回答
-2

当服务器拥有由根 CA(例如 Verisign)签名的 sub-ca-A 签名的证书时,服务器会将所有证书作为服务器 hello 的一部分发送,以便可以验证服务器的证书。

在您的情况下,您在信任库中只有根 CA。

因此,由于您缺少 sub-ca 证书,因此无法建立信任验证链。
这不仅是不可能的,而且能够做到这一点是错误的/不安全的。因此,您正在做的事情偏离了正确的道路。

所以你只有2个选择。
服务器的实际证书作为受信任的证书放入信任库中。
整个链放入信任库,即中间 CA 证书和根证书。

你有什么顾虑?中级证书过期?

于 2012-04-12T18:11:51.380 回答