我正在编写一个非常基本的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的链条只有两个,我用它们。
答案 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
谢谢!