Windows 上的 OpenSSL 可以使用系统证书存储吗?

Posted

技术标签:

【中文标题】Windows 上的 OpenSSL 可以使用系统证书存储吗?【英文标题】:Can OpenSSL on Windows use the system certificate store? 【发布时间】:2012-03-19 09:57:26 【问题描述】:

我从 Linux 移植到 Windows 的一些工作 C++ 代码在 Windows 上失败,因为 SSL_get_verify_result() 正在返回 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY

代码在 Linux 上使用 SSL_CTX_set_default_verify_paths() 告诉 SSL 仅在标准默认位置查找证书存储。

是否可以让 OpenSSL 使用系统证书存储?

【问题讨论】:

【参考方案1】:

没有。不是开箱即用的。

不,它不可能开箱即用。这将需要额外的编程。使用 OpenSSL,您有两个(开箱即用)选项:

    使用 OpenSSL 自己的证书存储(它是由 OpenSSL 提供的 perl 脚本创建的目录层次结构) 仅使用您创建的证书链文件(它是一个文本文件,其中包含信任链中的所有 PEM 编码证书)。创建这样一个文件很容易(只需附加它)

【讨论】:

是否可以从 windows pkcs 文件在内存中创建 PEM 文件?然后加载那个?我发现:marc.info/?l=openssl-users&m=119583966725315 描述了从 pkcs 包创建 PEM 文件...而***.com/questions/5052563/… 描述了从缓冲区加载 PEM 文件的机制...? 是的,这当然是可能的。 糟糕...由于某种原因,它不喜欢我的文件(使用该页面中的代码制作)...我会认为在我之前有人会这样做? 我很好奇您是否可以评论@Tushar Sudake 最近的解决方案...您认为这仍然无法使用 OpenSSL 吗? 是的,我认为这可能有效。此外,他写道,他已经这样做了,而且奏效了。当我写这不可能时,我的意思是“直接不可能”(例如,OpenSSL 直接使用来自 Windows 的证书)。【参考方案2】:

我之前做过。 希望这会有所帮助,如果这正是您正在寻找的。​​p>

    使用 Crypto API 从 Windows 证书存储区加载您的证书(在 PCCERT_CONTEXT 结构中)。 按原样以二进制格式获取其加密内容。 [PCCERT_CONTEXT->pbCertEncoded]。 使用 OpenSSL 的 d2i_X509() 方法将此二进制缓冲区解析为 X509 证书对象。 使用 SSL_CTX_get_cert_store() 方法获取 OpenSSL 信任库的句柄。 使用X509_STORE_add_cert() 方法将上述解析的X509 证书加载到此信任库中。 你完成了!

【讨论】:

感谢您的信息。我应该对此添加一些注意事项: 1. 使用“ROOT”(而不是“CA”)枚举 windows 的商店。 2.需要在connect/handshake前添加cert,connect/handshake后验证,否则验证失败。 这种方法的问题是它只验证中间证书。它不会验证您的中间证书是否不直接受信任,而是它们的根是否受信任。我们如何验证根是否受信任而不是中间证书?【参考方案3】:

是的

可以将OpenSSL 用于照常操作,而CryptoAPI 仅用于证书验证过程。我在这里看到了关于这个主题的几个线程,并且大多数都在附近/通过。

使用CryptoAPI,您必须:

使用CryptStringToBinary()PEM 解码为DER

使用CertCreateCertificateContext() 创建一个CERT_CONTEXT 对象

并通过众所周知的/记录在案的程序验证此表格中的证书。 (例如here at ETutorials。)

为了最后一步的工作,您还需要为MYROOTCA 系统存储之一初始化HCERTSTORE,或者遍历它们...取决于您想要的行为。

【讨论】:

【参考方案4】:

对于那些仍在为此苦苦挣扎的人,这里有一个示例代码可以帮助您入门:

#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#include <cryptuiapi.h>
#include <iostream>
#include <tchar.h>

#include "openssl\x509.h"

#pragma comment (lib, "crypt32.lib")
#pragma comment (lib, "cryptui.lib")

#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

int main(void)

    HCERTSTORE hStore;
    PCCERT_CONTEXT pContext = NULL;
    X509 *x509;
    X509_STORE *store = X509_STORE_new();

    hStore = CertOpenSystemStore(NULL, L"ROOT");

    if (!hStore)
        return 1;

    while (pContext = CertEnumCertificatesInStore(hStore, pContext))
    
        //uncomment the line below if you want to see the certificates as pop ups
        //CryptUIDlgViewContext(CERT_STORE_CERTIFICATE_CONTEXT, pContext,   NULL, NULL, 0, NULL);

        x509 = NULL;
        x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded);
        if (x509)
        
            int i = X509_STORE_add_cert(store, x509);

            if (i == 1)
                std::cout << "certificate added" << std::endl;

            X509_free(x509);
        
    

CertFreeCertificateContext(pContext);
CertCloseStore(hStore, 0);
system("pause");
return 0;


【讨论】:

您对d2i_X509 的使用无效,因为d2i_X509 增加了*in 参数(您使用强制转换以避免编译器错误)。您必须使用临时变量来避免内存问题,例如:const unsigned char *encoded_cert = win_cert_context-&gt;pbCertEncoded; d2i_X509(nullptr, &amp;encoded_cert, ... pContext 将在传递给 CertFreeCertificateContext() 时为 NULL(因为 while 循环不会提前中断),因此不需要调用。

以上是关于Windows 上的 OpenSSL 可以使用系统证书存储吗?的主要内容,如果未能解决你的问题,请参考以下文章

无法从 Windows 上的 /usr/local/ssl/openssl.cnf 加载配置信息

无法打开配置文件:Windows 上的 /usr/local/ssl/openssl.cnf [重复]

我必须对我的 xampp (Windows) 上的 OpenSSL 扩展工作做些啥? :( [复制]

OpenSSL安装

从 Windows 上的 bash 脚本运行 Openssl - 主题不以“/”开头

Openssl CA证书生成以及双向认证,及windows系统证书批量导出,android cer转bks