【问题标题】:Another situation where I get X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY我得到 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 的另一种情况
【发布时间】:2018-10-30 08:49:04
【问题描述】:

作为这个原始问题的后续:

Unable to get certificate locally

我确实解决了 jww 回答的原始问题。

我现在已经按照相同的步骤从“comodo”导入我们公司网站的证书链。我只是将它们添加到我最初与“google.com”根证书一起使用的文件中。

现在,虽然这仍然适用于“google”,但当我连接到我们公司的网站时,我仍然在 SSL_get_verify_result() 调用中收到错误代码 20。

这是我们使用“通配符”证书的结果吗?即:*.domain.com。

我目前使用的OpenSSL版本是1.0.1g。

从我的角度来看,我没有看到任何其他差异。

感谢您的建议。

----- 更新了------

首先,让我评论一下,我没有提及我们的域,也没有发布太多来自 OpenSSL 命令的材料,因为我对应该保密的内容不够熟悉。

我所做的是将 base64 编码的证书合并到一个大文件中,如上一篇文章所述。我通过浏览器“导出”实用程序以相同的方式获得了它们。这意味着我们使用的证书以及我之前帖子中的 google 证书都是串联的。具体来说,它现在看起来像这样:

Our Company Cert -----BEGIN CERTIFICATE----- .... -----END CERTIFICATE----- and it is signed by these guys - ComodoRSA -----BEGIN CERTIFICATE----- .... -----END CERTIFICATE----- and that is signed at the root here - ComodoRoot -----BEGIN CERTIFICATE----- .... -----END CERTIFICATE----- and this is the GOOGLE G3 who signed the "www.google.com" -----BEGIN CERTIFICATE----- .... -----END CERTIFICATE----- and the GOOGLE G3 is signed by this one - globalSign -----BEGIN CERTIFICATE----- .... -----END CERTIFICATE-----

那么我用来测试的代码段是这样的:

strcpy(host,"our.domain.com");
//  strcpy(host,"www.google.com");
/* Build our SSL context*/
ctx = initialize_ctx(KEYFILE,NULL);

/* Connect the TCP socket*/
sock = tcp_connect(host,port);

后来……

result = SSL_get_verify_result(ssl);
switch(result) {
case X509_V_ERR_CERT_HAS_EXPIRED : break;
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN : break;
case X509_V_OK : break;
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT : break;
default :puts("Certificate doesn't verify");
}

简单地说,相同的代码,使用相同的 CRT 文件,在我使用 www.google.com 主机时不会给我一个“20”错误,但在我使用我们的主机时确实给我一个错误“20”服务器。测试范围涉及更改已注释掉的主机名称。

与商业客户端(Chrome、IE、FF...)的 HTTPS 服务器连接没有错误。

至于推荐该命令的评论,我得到以下信息(希望我粘贴了必要的信息):

对于谷歌:

depth=2 OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign verify return:1
depth=1 C = US, O = Google Trust Services, CN = Google Internet Authority G3
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = www.google.com
verify return:1
read:errno=0
----   other stuff ----
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
   i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
 1 s:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
   i:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
---

对于我们的域,我得到以下信息(隐藏公司细节):

depth=2 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority
verify error:num=20:unable to get local issuer certificate
verify return:0
read:errno=10054
----   other stuff ---
Certificate chain
 0 s:/C=US/postalCode=00000/ST=IL/L=city/street=main/O=company./OU=PremiumSSL Wildcard/CN=*.domain.com
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
 1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
    i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
 2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
    i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
----

现在,链条是我们的证书是由“ComodoRSA”签名的,并且它是由“ComodoRoot”签名的。

但是,正如我最初指出的那样,我们的证书是“通配符”证书,而 google 证书不是。

这就是我的问题:在 openSSL 1.0.1g 版本中使用通配符证书有问题吗?

--- EDIT2 ----

我正在为帖子添加更多内容,因此我可以包含来自浏览器的图片。

我们的证书在实时网站上,不是自签名的。

我正在检查未显示的部分代码中的通用名称。在这篇文章中,我只希望针对此错误提供建议。

我找到了一个使用与我们相同的链的网站:DrudgeReport.com

我只是用浏览器提取了证书,并将它们保存到一个文件中。这与我在 google.com 站点中使用的步骤相同。 (查看证书并复制到文件)

Drudge 的结果是错误 19,它是“自签名”,而不是错误 20,这是我的错误。当我从任一站点复制到文件时(如我所料),根级别(comodo 安全)是相同的。

当我从您的 cmets 和链接中了解到这一点时,我看到下一个中​​间问题是:我如何知道服务器正在发送哪些证书,以及哪些证书在商店中?然后我会知道要导入哪个。您提供的 openssl 命令输出中的指示符是什么(如果有)?

openssl 上的教育材料很难找到。只是很多文档,对于像我这样的新手来说,其定义相当循环。

感谢您迄今为止的反馈。

【问题讨论】:

  • 我认为你需要提供更多关于你真正做了什么的细节。虽然我可以根据您的上一个问题和您在此处写的内容了解您可能做了什么,但我认为这不是您所做的——因为它不起作用。因此,请至少提供您使用SSL_CTX_load_verify_locations 加载的文件中的确切证书的详细信息,以及验证您的公司证书实际上需要哪些证书。另外,检查openssl s_client -connect yourcompany:443 -CAfile ca.pem 是否成功地使用您的 CA 文件验证了证书。
  • @Steffen Ullrich 该帖子已更新,包含更多信息。当你说“因为它不起作用”时,我对“google”连接做了同样的操作,就像我们的一样。那么为什么它不起作用是我试图确定的......我看到的唯一不同的是谁签署了证书,而我们的是“通配符”。

标签: ssl openssl certificate


【解决方案1】:

这就是我的问题:在 openSSL 1.0.1g 版本中使用通配符证书有问题吗?

不是通配符证书的问题。实际上,您的代码甚至根本不检查证书的主题(即您的代码不安全),它主要检查证书链、证书的到期时间和用途。而来自openssl s_client 的错误信息清楚地指出了问题所在:

验证错误:num=20:unable to get local issuer certificate

因此,问题不在于证书主体,而在于它找不到本地信任锚。查看服务器提供的证书链会得到以下证书链:

 [1] CN=*.domain.com, issued by [2]
 [2] CN=COMODO RSA Organization Validation Secure Server CA, issued by [3]
 [3] CN=COMODO RSA Certification Authority, issued by [ROOT]

预期的 [ROOT] 是“CN=AddTrust External CA Root” - 只有此 CA 不在您的受信任根 CA 列表中。

虽然您没有提供您在本地信任存储中拥有的证书的详细名称,但我猜测您称为“ComodoRoot”的 CA 类似于我在名单。只是,在您的信任存储中,它可能是证书的自签名版本,而在服务器提供的证书链中,它是由“[ROOT] CN=AddTrust External CA Root”颁发的证书。两个证书具有相同的公钥和私钥,这意味着证书链中的签名可以通过两者成功验证。

但是,您使用的旧版本(长期不受支持的版本)OpenSSL 无法正确处理这种情况。它将遵循服务器发送的证书链,然后期望链中的最后一个证书由您的信任存储中的一个证书签名。如果失败,它将不会检查是否可以成功验证较短的链。

这意味着如果您的信任库中有“CN=AddTrust External CA Root”,或者如果服务器发送一个以“[2] CN=COMODO RSA Organization Validation Secure Server CA”结尾的短链,它将成功,因为然后它会在您的信任库中找到此发行者(您的“ComodoRoot”,即“CN=COMODO RSA 证书颁发机构”)。

有关此问题的更详细说明,请参阅 stackoverflow.com 上的 this answerthis article。请注意,使用 OpenSSL 1.0.1 无法在代码中解决此问题 - 您需要将丢失的证书添加到您的信任存储区或更改服务器发送的证书链。

【讨论】:

  • @SpacemanScott:openssl s_client 的输出显示了服务器实际发送的证书,而浏览器中的输出显示了信任链计算由浏览器 - 这是不同的。同样,问题在于您使用的旧版本 OpenSSL 如何确定它需要的根 CA。您要么需要解决它,但需要从 AddTrust 提供预期的根 CA,要么让服务器发送更短的链或升级到不再出现此问题的较新版本的 OpenSSL。
猜你喜欢
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
  • 2011-10-01
  • 2017-08-09
  • 2019-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多