繁体   English   中英

在Windows上获取根CA证书的可靠方法

[英]Reliable way to get root CA certificates on Windows

我正在使用boost asio连接到我的有效证书(由根CA签名)。 我使用的代码是boost文档提供的ssl客户端示例

我添加的唯一一行是:

boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23_client);
ctx.set_default_verify_paths(); <------------- Add default verification paths
ctx.set_password_callback(&password_callback);    

client c(io_service, ctx, iterator);

io_service.run();

问题是:当将此代码与本地安装的openSSH副本(从msi安装程序安装)一起使用时,可以正确找到路径并验证我的证书。 当我下载自己的openSSH存储库副本并进行编译时,此行不再起作用,并且我没有根CA证书来验证自己的证书(因此失败 )。

由于我最终希望将这些客户端分发到客户计算机上,因此我想避免设置环境变量,例如SSL_CERT_DIR等。 如何通过boost asio可靠地找到根CA证书,或者从源代码编译配置我的openSSH以找到它们?

您可以从Windows CA存储中加载根CA。 它已经包含“默认”受信任的根CA证书,可以通过certmgr进行管理。 在Windows下使用以下函数替换set_default_verify_paths:

#include <boost/asio/ssl/context.hpp>
#include <wincrypt.h>

void add_windows_root_certs(boost::asio::ssl::context &ctx)
{
    HCERTSTORE hStore = CertOpenSystemStore(0, "ROOT");
    if (hStore == NULL) {
        return;
    }

    X509_STORE *store = X509_STORE_new();
    PCCERT_CONTEXT pContext = NULL;
    while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != NULL) {
        X509 *x509 = d2i_X509(NULL,
                              (const unsigned char **)&pContext->pbCertEncoded,
                              pContext->cbCertEncoded);
        if(x509 != NULL) {
            X509_STORE_add_cert(store, x509);
            X509_free(x509);
        }
    }

    CertFreeCertificateContext(pContext);
    CertCloseStore(hStore, 0);

    SSL_CTX_set_cert_store(ctx.native_handle(), store);
}

这将从Windows ca存储中加载证书。 它使用d2i_X509将其转换为内部OpenSSL格式,并将其添加到OpenSSL X509_STORE。 然后,SSL_CTX_set_cert_store将该存储附加到boost ssl上下文。 您可以使用它来设置您的ssl上下文:

namespace ssl = boost::asio::ssl;
ssl::context ctx(ssl::context::tlsv12_client);
ctx.set_options(ssl::context::default_workarounds
                            | ssl::context::no_sslv2
                            | ssl::context::no_sslv3
                            | ssl::context::tlsv12_client);

#if BOOST_OS_WINDOWS
add_windows_root_certs(ctx);
#else
ctx.set_default_verify_paths();
#endif

ctx.set_password_callback(&password_callback);

client c(io_service, ctx, iterator);

io_service.run();

注意:您可能需要将crypt32添加到链接的库中。

注意2:BOOST_OS_WINDOWS需要Boost Predef

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM