如何在OpenSSL Windows中使用SSL_CERT_FILE(OpenSSL 1.0.1c)

Jer*_*rle 3 openssl windows-applications

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

各种研究使我下载了12月份版本的Mozilla PEM格式的可信证书,从这里开始:http://curl.haxx.se/docs/caextract.html 这包含所有连接到一起的证书和各种相关信息.一个文件.

我发现了对依赖OpenSSL的其他产品使用环境变量SSL_CERT_DIR和SSL_CERT_FILE的各种引用.例如,http://lynx.isc.org/current/README.sslcerts表示可以设置这两个,并且底层的OpenSSL库将使用它们.但是,这不是我使用OpenSSL工具本身的经验.

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

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

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

mklink a302054c.0"Verisign Intl Server.cer"

同样适用于Verisign的其他证书.然后我把Wells Fargo证书.在不同的目录中,并能够使用成功验证它

设置SSL_CERT_DIR = C:\ ca_stuff openssl验证"Wells Fargo web.cer"

但是,在定义SSL_CERT_FILE后,指向从cURL站点下载的下载的cacert.pem,相同的命令失败.无论是否定义了SSL_CERT_DIR,它都会这样做.我确认必要的CA证书在捆绑中,并确认其序列号与我从IE手动提取的序列号相匹配.

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

提前感谢您提供任何建议,见解和帮助.

jww*_*jww 6

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

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

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

Startcom的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
...
Run Code Online (Sandbox Code Playgroud)

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

嗯,这是你可以使用的列表之一.当你使用Mozilla的列表时,你会说"我相信Mozilla做正确的事".请记住,当Trustwave被拦截拦截SSL/TLS流量时,Mozilla会奖励Trustwave的不良行为.尽管Trustwave违反了至少两个包含策略,但Mozilla继续将它们包括在内,因为Trustwave承诺永远不会再这样做.有关详细信息,请参阅从受信任的根证书中删除Trustwave证书.

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

使用不同供应商的清单通常相当于交换你所知道的魔鬼你不知道的魔鬼.例如,Apple有一个他们使用的列表,您可以在iOS上检查:可用的受信任根证书列表(iOS 7).但Apple的列表有很多问题:http://seclists.org/fulldisclosure/2013/Sep/186http://seclists.org/fulldisclosure/2013/Sep/184.

我建议您建立自己的列表或固定证书.固定证书或公钥更好,因为它可以中和SSL/TLS中的系统性问题,使Trustwave能够完成他们的工作.有关详细信息,请参阅OWASP的证书和公钥固定.


...在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"
Run Code Online (Sandbox Code Playgroud)

x509_def.c用途X509_CERT_FILE_EVP:

const char *X509_get_default_cert_file_env(void)
    { return(X509_CERT_FILE_EVP); }
Run Code Online (Sandbox Code Playgroud)

X509_get_default_cert_file_env用于在by_file.cby_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);
Run Code Online (Sandbox Code Playgroud)

因此,在使用时,首选PEM格式(必需?)SSL_CERT_FILE.

最后,确保SSL_CERT_FILE没有被配置文件设置覆盖.有关详细信息,请参阅OpenSSL config(5).


手动提取每个证书并将其放在自己的文件中并使用指向它的哈希链接似乎是一个艰难的过程.

我不相信你需要使用时老调重弹SSL_CERT_FILE,-CAfileSSL_CTX_load_verify_locations.

使用时,我从来没有改头换面-CAfile或者SSL_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
...
Run Code Online (Sandbox Code Playgroud)

和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;
Run Code Online (Sandbox Code Playgroud)

如果SSL_CTX_load_verify_locations失败可以.这意味着你不会相信任何东西,所以你失败了关闭或关闭.