ssl - 与公共(public)服务器的 OPENSSL 连接给出 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY

标签 ssl openssl certificate

我正在编写一个非常基本的 SSL 客户端来连接到 HTTPS 网络服务器。我可以很好地连接和处理请求/响应。然而 OpenSSL 正在报告 UNABLE_TO_GET_ISSUER_CERT_LOCALLY,但到目前为止我选择忽略错误 :-)。现在我想解决这部分问题。

我通过连接到 HTTPS 上的公共(public) SSL 服务器(例如 Google 或 Yahoo)进行测试,并检查 SSL_get_verify_result(...) 的返回值。

据我了解,我需要该特定站点的 CA pem 文件,以便 OpenSSL 可以验证到可信证书颁发机构的链。在这种情况下,这将是为 Google 或 Yahoo 签署证书的机构。

为了获得我期望的 PEM 文件,我打开了我的 FireFox,导航到这些站点,执行了查看证书并将每个文件导出到列表中。因此,例如,我有一个名为“GeoTrustGlobalCA.pem”的文件,它看起来都不错。事实上,当我直接访问 GeoTrust 站点并下载他们的根证书时,正如我所料,它与我从 FireFox 导出的根证书相同。

因此,例如 Google 在 FireFox 的树中显示了两个证书,我加载每个:

result = SSL_CTX_load_verify_locations(ctx,"GoogleInternetAuthorityG2.pem",NULL);
if (result == 0) {
    puts("Opps...  Can't load the certificate");
}

result = SSL_CTX_load_verify_locations(ctx,"GeoTrustGlobalCA.pem",NULL);
if (result == 0) {
    puts("Opps...  Can't load the certificate");
}

之后,连接和交流的常规内容:

BIO_set_conn_hostname(bio, "www.google.com:https");

并且在加载或连接时不会出错。

但是,验证不起作用。

result = SSL_get_verify_result(ssl);
printf("The Verify Result is %d \n",result);

我得到返回值 UNABLE_TO_GET_ISSUER_CERT_LOCALLY(错误代码 20)

那么,我是不是漏掉了一些概念?这不会给我 X509_V_OK 结果,因为它有受信任的证书吗?只有两个来自 google.com 的上链,我使用了它们。

最佳答案

SSL_CTX_load_verify_locations 的第二次调用替换了第一次调用的证书。

你应该将你的根合并到一个文件中:

$ cat my-trusted-roots.pem
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----

然后使用 SSL_CTX_load_verify_locations 加载该单个文件。请参阅 OpenSSL docs on SSL_CTX_load_verify_locations .特别是NOTES部分:

If CAfile is not NULL, it points to a file of CA certificates in PEM format. The file can contain several CA certificates identified by

-----BEGIN CERTIFICATE-----

... (CA certificate in base64 encoding) ...

-----END CERTIFICATE-----

sequences. Before, between, and after the certificates text is allowed which can be used e.g. for descriptions of the certificates.


这里只是自行车脱落...

result = SSL_get_verify_result(ssl);
printf("The Verify Result is %d \n",result);

这是您需要执行的三个测试之一。

您需要执行的第二个测试如下。匿名 Diffie-Hellman (ADH) 不使用证书,因此您需要进行检查。

X509* cert = SSL_get_peer_certificate(ssl);
if(cert) X509_free(cert);

if(cert == NULL)
    /* Error - Anonymous Diffie-Hellman */

SSL_get_peer_certificate 会增加证书的引用计数,因此您需要对 X509_free 进行匹配调用。

您需要执行的第三项测试是主机名匹配。 OpenSSL 1.1.0 执行主机名匹配(和其他名称匹配,如 PKCS9 电子邮件地址);但较小的版本,如 0.9.8 和 1.0.1,不要执行匹配。

关于ssl - 与公共(public)服务器的 OPENSSL 连接给出 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24315526/

相关文章:

javascript - 是否通过浏览器发送没有名称 =“” 的输入字段

ssl - keystore 中的 "paired"证书和 key 是什么样的?

ssl - 关于 CSR 和 SSL 证书的问题

linux - OpenSSL命令行解密打嗝

c - 如何播种 PRNG 以与 BN_rand* 一起使用?

wcf - azure acs中可以同时拥有客户端证书安全和服务身份认证吗

Python - SSL 客户端/服务器证书

web-applications - Web 应用程序的 SSL 证书

PHP OpenSSL openssl_get_cert_locations

ssl - 我可以在同一台机器上为我自己的服务器使用为 nginx 创建的证书吗?