【问题标题】:How to use SSL_CERT_FILE for OpenSSL Windows (OpenSSL 1.0.1c)如何将 SSL_CERT_FILE 用于 OpenSSL Windows (OpenSSL 1.0.1c)
【发布时间】:2012-12-26 12:19:19
【问题描述】:

如何(如果有的话)为 OpenSSL 定义一个受信任的证书文件 在 Windows(Win-7,OpenSSL 1.0.1c)上使用 SSL_CERT_FILE 环境变量?

各种研究让我下载了 Mozilla 的 12 月 '12 版本 PEM 格式的受信任证书,来自此处:http://curl.haxx.se/docs/caextract.html 这包含连接在一起的所有证书和各种相关信息 到一个文件中。

我找到了各种关于环境变量使用的参考资料 SSL_CERT_DIR 和 SSL_CERT_FILE 相对于其他依赖于 OpenSSL。例如,http://lynx.isc.org/current/README.sslcerts 表示 可以同时设置这两个,并且底层的 OpenSSL 库将使用 他们。但是,这并不是我对 OpenSSL 工具本身的体验。

我能够成功使用 SSL_CERT_DIR,但是非常痛苦,如下所示。 我从 www.wellsfargo.com 导出(从 IE 8)证书(选择 随机),以及其信任链中的两个证书,均来自 威瑞信。我将两个 Verisign 证书中的每一个都放在目录 C:\ca_stuff 中, 并为每个生成一个哈希

openssl x509 -hash -noout -in "Verisign Intl Server.cer"

它输出了a302054c,并由此创建了一个链接

mklink a302054c.0 "Verisign Intl Server.cer"

同样适用于其他威瑞信证书。然后我把富国银行的证书。在 一个不同的目录,并且能够使用成功验证它

设置 SSL_CERT_DIR=C:\ca_stuff openssl 验证“富国银行 web.cer”

但是,定义 SSL_CERT_FILE 后,指向下载的 cacert.pem 从 cURL 站点下载,相同的命令失败。它这样做了 没有定义 SSL_CERT_DIR。我验证了必要的 CA 证书在捆绑包中,并确认它们的序列号匹配 我从 IE 中手动提取的那些。

手动提取每个证书并将其放入似乎是一个艰巨的过程 它在自己的文件中,并带有指向它的哈希链接。如果这是 Unix,我 可以自动化它,但在 Windows 上...我显然误解了如何让一个大型 CA 证书文件与 OpenSSL 一起使用。

提前感谢您提供的任何建议、见解和帮助。

【问题讨论】:

    标签: openssl windows-applications


    【解决方案1】:

    如何(如果有的话)为 OpenSSL 定义一个受信任的证书文件

    CAFile 只是您信任并希望使用的自签名证书的串联。如果您只想信任一个,那么 CA 文件中应该只有一个。

    我更喜欢 PEM 编码,因为它更易于使用文本编辑器(-----BEGIN CERTIFICATE----------END CERTIFICATE-----)进行检查。例如,这是来自 Startcom (http://www.startssl.com/certs/) 的 ca-bundle.pem:

    所以,要创建一个,只需使用cat 和重定向(或复制和粘贴):

    # Empty my-ca-file.pem
    echo "" > my-ca-file.pem
    # Add Startcom certs
    cat startcom-ca-bundle.pem >> my-ca-file.pem
    # Add others as desired
    ...
    

    各种研究让我下载了 12 年 12 月版本的 PEM 格式的 Mozilla 可信证书...

    嗯,这是您可以使用的列表之一。当您使用 Mozilla 的列表时,您是在说“我相信 Mozilla 会做正确的事”。请记住,当 Trustwave 被发现拦截 SSL/TLS 流量时,Mozilla 奖励了 Trustwave 的不良行为。尽管 Trustwave 至少违反了两项包容政策,但 Mozilla 继续将它们包括在内,因为 Trustwave 承诺再也不会这样做。详情请见Remove Trustwave Certificate(s) from trusted root certificates

    如果您不相信 Mozilla 的判断,那么您可以使用 OpenSSL 的内置列表 /usr/lib/ssl/certs/ca-certificates.crt,使用另一个列表(大多数主要供应商都有),或者构建您自己的列表。

    使用不同的供应商名单通常相当于用你认识的魔鬼换你不认识的魔鬼。例如,Apple 有一个他们使用的列表,您可以在iOS: List of available trusted root certificates (iOS 7) 进行检查。但是苹果的列表有很多问题:http://seclists.org/fulldisclosure/2013/Sep/186http://seclists.org/fulldisclosure/2013/Sep/184

    我建议您建立自己的列表或固定证书。固定证书或公钥更好,因为它消除了 SSL/TLS 中的系统性问题,这些问题允许 Trustwave 做他们所做的事情。详情请参阅 OWASP 的Certificate and Public Key Pinning


    ...在 Windows(Win-7、OpenSSL 1.0.1c)上使用 SSL_CERT_FILE 环境变量?

    我不知道如何通过环境变量来做到这一点,因为我不使用它们。但是 Linux/Unix/OSX/Windows 之间应该没有区别(可能除了长文件名和空格的处理)。

    查看 OpenSSL 源代码,您在 cryptlib.h 中有以下内容:

    #define X509_CERT_FILE_EVP       "SSL_CERT_FILE"
    

    x509_def.c 使用X509_CERT_FILE_EVP

    const char *X509_get_default_cert_file_env(void)
        { return(X509_CERT_FILE_EVP); }
    

    X509_get_default_cert_file_envby_file.c中使用by_file_ctrl

    ...
    switch (cmd)
    {
        case X509_L_FILE_LOAD:
            if (argl == X509_FILETYPE_DEFAULT)
            {
                file = (char *)getenv(X509_get_default_cert_file_env());
                if (file)
                    ok = (X509_load_cert_crl_file(ctx,file,
                                                  X509_FILETYPE_PEM) != 0);
    
                else
                    ok = (X509_load_cert_crl_file(ctx,X509_get_default_cert_file(),
                                                  X509_FILETYPE_PEM) != 0);
    
                if (!ok)
                {
                    X509err(X509_F_BY_FILE_CTRL,X509_R_LOADING_DEFAULTS);
                }
            }
            else
            {
                if(argl == X509_FILETYPE_PEM)
                    ok = (X509_load_cert_crl_file(ctx,argp,
                                                  X509_FILETYPE_PEM) != 0);
                else
                    ok = (X509_load_cert_file(ctx,argp,(int)argl) != 0);
            }
            break;
    }
    return(ok);
    

    因此,在使用SSL_CERT_FILE 时,首选(必需?)PEM 格式的串联。

    最后,确保SSL_CERT_FILE 未被配置文件设置覆盖。详情请见OpenSSL config(5)


    手动提取每个证书并将其放入自己的文件中并带有指向它的哈希链接似乎是一个艰巨的过程。

    我认为您在使用 SSL_CERT_FILE-CAfileSSL_CTX_load_verify_locations 时不需要重新散列。

    我在使用-CAfileSSL_CTX_load_verify_locations 时从未重复过,一切正常。当事情破裂时,通常是因为(1)根证书不存在或不可信;或 (2) 中间证书不存在。

    对于上面的第(2)项,您需要服务器发送所有必需的证书来构建链。否则,客户将不知道到哪里寻找丢失的中间证书。是 PKI 中一个众所周知的问题,称为“哪个目录”问题(客户端不知道要在哪个 X500 目录中搜索丢失的证书)。


    相关,这里是如何在 OpenSSL 的s_client 中使用它们。这实际上是有效的,因为 pagepeeker.com 使用 StartCom,如果您省略 -CAfile 选项,它将失败:

    $ echo "GET / HTTP\1.1" | openssl s_client -connect api.pagepeeker.com:443 -CAfile startcom-ca-bundle.pem
    CONNECTED(00000003)
    depth=2 C = IL, O = StartCom Ltd., OU = Secure Digital Certificate Signing, CN = StartCom Certification Authority
    verify error:num=19:self signed certificate in certificate chain
    verify return:0
    ---
    Certificate chain
     0 s:/description=8CTO6gSuxeRRsIXl/C=RO/CN=api.pagepeeker.com/emailAddress=alexandru.florescu@gmail.com
       i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
     1 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Class 1 Primary Intermediate Server CA
       i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
     2 s:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
       i:/C=IL/O=StartCom Ltd./OU=Secure Digital Certificate Signing/CN=StartCom Certification Authority
    ---
    Server certificate
    -----BEGIN CERTIFICATE-----
    MIIGZTCCBU2gAwIBAgIDCJkoMA0GCSqGSIb3DQEBBQUAMIGMMQswCQYDVQQGEwJJ
    TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
    ...
    

    以及做C编程时的相关代码。这是我用来设置 SSL/TLS 连接的代码的一部分(除了公钥固定):

    int ret = 0;
    unsigned long ssl_err = 0;
    SSL_CTX* ctx = NULL;
    
    do
    {
        ret = SSL_library_init();
        ssl_err = ERR_get_error();
        if(!(1 == ret))
        {
            display_error("SSL_library_init", ssl_err);
            break; /* failed */
        }
    
        /* SSLv23_method() is 'everything' */
        const SSL_METHOD* method = SSLv23_method();
        ssl_err = ERR_get_error();
        if(!(NULL != method))
        {
            display_error("SSLv23_method", ssl_err);
            break; /* failed */
        }
    
        /* http://www.openssl.org/docs/ssl/ctx_new.html */
        ctx = SSL_CTX_new(method);
        ssl_err = ERR_get_error();
        if(!(ctx != NULL))
        {
            display_error("SSL_CTX_new", ssl_err);
            break; /* failed */
        }
    
        /* Enable standard certificate validation and our callback */
        /* https://www.openssl.org/docs/ssl/ctx_set_verify.html */
        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, my_verify_cb);
        /* Cannot fail ??? */
    
        /* Remove most egregious */
        const long flags = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
        long old_opts = SSL_CTX_set_options(ctx, flags);
        UNUSED(old_opts);
    
        /* http://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html */
        ret = SSL_CTX_load_verify_locations(ctx, "startcom-ca-bundle.pem", NULL);
        ssl_err = ERR_get_error();
        if(!(1 == ret))
            display_warning("SSL_CTX_load_verify_locations", ssl_err);
    
    } while(0);
    
    // Use context
    return ctx;
    

    如果SSL_CTX_load_verify_locations 失败也没关系。这意味着您不会信任任何东西,因此您无法关闭或关闭。

    【讨论】:

      猜你喜欢
      • 2018-02-06
      • 2016-04-20
      • 2018-12-24
      • 1970-01-01
      • 1970-01-01
      • 2017-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多