使用包含两个CA签名证书和一个自签名证书的Verisign链证书进行SSL握手失败

48

我遇到了一个问题并试图进行调试。我们购买了一个Verisign证书。当我们使用以下代码:

openssl> s_client -connect myweb.com:443 -showcerts

SSL握手永远无法完成,在最后我们看到错误:

Verify return code: 19 (self signed certificate in certificate chain)

它显示了3个---BEGIN/END CERTIFICATE---标记。链中的两个证书是Verisign签名的,但一个是自签名的。

  1. 如果有人能解释一下这个自签名证书如何出现在CA签名证书中,那么请讲解一下?

  2. 这个错误19(certificate chain中的自签名证书)是无害的吗?如果不是,可能是什么原因导致的呢?

  3. 客户端在信任商店中具有CA证书,但没有自签名证书。您认为这可能会导致问题吗?如果是,我该如何:

    1. 如何从链证书中摆脱自签名证书,只留下2个CA签名证书?
    2. 将此自签名证书添加到客户端受信任的存储中?

谢谢Brettski。我会检查中间证书。我想添加更多信息:当客户端发送上述openssl命令时,“客户端hello”到达服务器,但我们从未在客户端收到“服务器hello”。如果中间证书丢失,您是否期望出现这种行为?设备是Windows移动设备,服务器是Apache Web服务器。 - curiousone
证书加载在哪种类型的服务器/设备上? - Brettski
你能否从其他设备/计算机通过OpenSSL连接?我使用Windows Mobile的哪个版本,我曾经在Windows Mobile和安全证书方面有过噩梦般的经历。 - Brettski
尝试向服务器发送一个空行作为输入:echo "" | openssl .... - Jason Harrison
5个回答

79

CAs发布的根证书只是自签名证书(可能用于发放中间CA证书)。除了它们已经成功地在许多浏览器或OS信任锚点中被默认导入,它们没有什么特别之处。

尽管浏览器和一些工具已配置为默认查找受信任的CA证书(其中有些可能是自签名的),但就我所知,openssl命令并没有这样做。

因此,任何提供完整证书链的服务器(从其终端实体证书[服务器的证书]到根CA证书[可能含中间CA证书])都将在证书链中具有一个自签名证书:根CA。

openssl s_client -connect myweb.com:443 -showcerts没有特殊理由信任Verisign的根CA证书,并且因为它是自签名的,您将得到"self signed certificate in certificate chain"。

如果您的系统有一个默认信任一组证书的位置(例如RedHat/Fedora上的/etc/pki/tls/certs和Ubuntu/Debian上的/etc/ssl/certs),则可以配置OpenSSL将其用作信任锚点,例如像这样:

openssl s_client -connect myweb.com:443 -showcerts -CApath /etc/ssl/certs

2
在OS X中,-CApath会是什么? - Jonathan
6
默认情况下,我认为OSX没有这个功能,因为它依赖于钥匙串。您可以进入钥匙串访问应用程序,在“系统根证书”中选择所有证书(如果有的话,除了那些被划掉的),右键单击并将所有项目导出到PEM文件中,然后使用“-CAfile”(而不是“-CApath”)来指向该文件。 - Bruno
2
@Bruno 我怎样在Windows中获取受信任的证书?它们存储在注册表中。我无法使用-CAfile和-CApath。 - Kahn
尝试使用 https://certifi.io/en/latest/ - "精心挑选的根证书集合,用于验证 SSL 证书的可信度,并验证 TLS 主机的身份"。它提供可下载的 CA 包或 Python/Ruby/Node/Go/Erlang 包。 - Greg Dubicki
4
我仍然收到“verify error:num=19:self signed certificate in certificate chain”错误提示。 - Janac Meena
我只能让“-CAfile”起作用,不确定为什么“-CApath”无法工作。 - BLang

9

5
关于服务器是否可以向客户端传送根证书,从RFC-5246《传输层安全性(TLS)协议版本1.2》文档中提取的内容如下:
certificate_list 这是一系列(链式)证书。发送方的证书必须在列表中首先出现。每个后续证书必须直接验证前面的证书。因为证书验证要求根密钥独立分发,指定根证书颁发机构的自签名证书可以在链式证书中省略,可以假设远程端必须已经拥有它以便在任何情况下验证它。
关于“MAY”术语,从RFC-2119《最佳当前实践》中提取的内容如下:
5.MAY 这个词或形容词“OPTIONAL”表示该项是真正的可选项。一个供应商可能会选择包含该项,因为特定的市场需要它或者因为供应商认为它增强了产品,而另一个供应商可能会省略相同的项。不包括特定选项的实现必须准备好与包括该选项的另一个实现进行互操作,尽管可能功能会降低。同样,包括特定选项的实现必须准备好与不包括该选项的另一个实现进行互操作(当然,除了该选项提供的功能)。
总之,在握手期间服务器可以在证书路径中传递根证书。
实际用途。 不要考虑浏览器用户术语,而是考虑限制互联网访问的军事化区域中的服务器上的传输工具。服务器在传输中扮演客户端角色,接收来自服务器的所有证书路径。必须检查链式证书中的所有证书是否可信,包括根证书。唯一的检查方法是将根证书包含在传输时间的证书路径中,并与以前声明为“受信任”的本地副本进行匹配。

3

尝试在Mac上使用了Safari、Firefox和Chrome,以及在Win上使用IE和Firefox这些浏览器。但不幸的是,在所有情况下都失败了。POS。 - CarpeNoctem

1
当您看到“Verify return code: 19 (self signed certificate in certificate chain)”时,要么服务器真的在尝试使用自签名证书(客户端永远无法验证),要么OpenSSL没有访问所需的根证书,但服务器正在尝试提供它本身(这是不应该的,因为客户端永远无法信任服务器提供与服务器自己证书相对应的根证书)。
再次,添加-showcerts将有助于您诊断哪个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接