如何(如果有的话)为 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
...
各种研究使我下载了 PEM 格式的 Mozilla 受信任证书的 12 月 '12 版本...
嗯,这是您可以使用的列表之一。当您使用 Mozilla 的列表时,您是在说“我相信 Mozilla 会做正确的事”。请记住,当 Trustwave 被发现拦截 SSL/TLS 流量时,Mozilla 奖励了 Trustwave 的不良行为。尽管 Trustwave 至少违反了两项包含政策,但 Mozilla 仍继续将其包含在内,因为 Trustwave 承诺不再这样做。有关详细信息,请参阅从受信任的根证书中删除 Trustwave 证书。
如果您不相信 Mozilla 的判断,那么您可以使用 OpenSSL 的内置列表/usr/lib/ssl/certs/ca-certificates.crt
,使用另一个列表(大多数主要供应商都有),或者构建您自己的列表。
使用不同的供应商名单通常相当于用你认识的魔鬼换你不认识的魔鬼。例如,Apple 有一个您可以在iOS 上检查的列表:可用的受信任根证书列表 (iOS 7)。但是苹果的列表有很多问题:http ://seclists.org/fulldisclosure/2013/Sep/186和http://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"
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_env
用于:by_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
.
最后,确保SSL_CERT_FILE
没有被配置文件设置覆盖。有关详细信息,请参阅OpenSSL 配置 (5)。
手动提取每个证书并将其放入自己的文件中并带有指向它的哈希链接似乎是一个艰巨的过程。
我认为您在使用 , 或 时不需要SSL_CERT_FILE
重新-CAfile
散列SSL_CTX_load_verify_locations
。
-CAfile
使用or时我从来没有重复过SSL_CTX_load_verify_locations
,一切都很好。当事情破裂时,通常是因为(1)根证书不存在或不可信;(2) 没有中间证书。
对于上面的第 (2) 项,您需要服务器发送所有必需的证书来构建链。否则,客户将不知道到哪里寻找丢失的中间证书。是 PKI 中一个众所周知的问题,称为“哪个目录”问题(客户端不知道要在哪个 X500 目录中搜索丢失的证书)。
相关的,这里是如何在 OpenSSL 的s_client
. -CAfile
这实际上有效,因为 pagepeeker.com 使用 StartCom,如果您省略该选项,它将失败:
$ 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
如果失败了也没关系。这意味着你不会信任任何东西,所以你失败了关闭或关闭。