OPENSSL与公共服务器的连接提供X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY

时间:2014-06-19 20:15:12

标签: ssl openssl certificate

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

我正在通过连接到HTTPS上的公共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 (error code 20)

那么,我在这里错过了一些概念吗?这不会给我X509_V_OK结果,因为它有可靠的证书吗?来自google.com的链条只有两个,我用它们。

2 个答案:

答案 0 :(得分:2)

第二次拨打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。在partuclar中, NOTES 部分:

  

如果CAfile不为NULL,则它指向PEM中的CA证书文件   格式。该文件可以包含由

标识的多个CA证书      

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

     

...(base64编码的CA证书)......

     

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

     

序列。允许证书文本之前,之间和之后   可以使用例如有关证书的说明。


在这里骑自行车脱落......

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, DO NOT 执行匹配。

答案 1 :(得分:2)

由于这篇文章,我终于可以使SSL/TLS Client在Windows上工作了。我built openssl using MSYS2。我必须对openssl-bio-fetch.tar.gz代码进行一些更改,以便它可以在Windows / MSYS2中构建/运行,主要是调整Makefile包含并设置-DNDEBUG以避免Posix信号。

但是在运行代码时,我得到了:

    $ ./openssl-bio-fetch.exe
    Warning: thread locking is not implemented
    verify_callback (depth=1)(preverify=0)
        Issuer (cn): DigiCert High Assurance EV Root CA
        Subject (cn): DigiCert SHA2 Extended Validation Server CA
        Error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
    certificate verify failed

我必须下载2个.pem文件:

DigiCert High Assurance EV Root CA

DigiCert SHA2 Extended Validation Server CA

并将证书粘贴到已由代码使用的同一.pem文件中:random-org-chain.pem

谢谢!

相关问题