以 PHP SSL 上下文选项“cafile”可接受的格式导出 HTTPS 证书

Mar*_*ryl 6 php ssl https openssl ca

如何以PHP SSL 上下文选项cafile可接受的格式导出证书?

我下面的代码用于openssl_x509_export将证书链导出stackoverflow.com到文件。该代码基于如何在 PHP 中使用 CURL 获取 SSL 证书信息?

$context = stream_context_create(["ssl" => ["capture_peer_cert_chain" => true]]);
$h = stream_socket_client(
         "ssl://stackoverflow.com:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT,
         $context);
$params = stream_context_get_params($h);

$ca = null;

foreach ($params["options"]["ssl"]["peer_certificate_chain"] as $cert)
{
    openssl_x509_export($cert, $output);
    $ca .= $output;
}

file_put_contents("cafile", $ca);
Run Code Online (Sandbox Code Playgroud)

(我知道没有必要导出整个链。)


然后,我尝试使用以下代码片段使用导出的文件连接到同一主机以验证证书。但是代码失败了:

PHP 警告:file_get_contents():SSL 操作失败,代码为 1。OpenSSL 错误消息:

错误:14090086:SSL 例程:SSL3_GET_SERVER_CERTIFICATE:第 22 行 /path/test.php 中的证书验证失败

$context = stream_context_create(["ssl" => ["cafile" => "cafile"]]);

file_get_contents("https://stackoverflow.com/", false, $context);
Run Code Online (Sandbox Code Playgroud)

文件格式有什么问题?

有趣的wget是对导出的证书感到满意,以下成功:

$context = stream_context_create(["ssl" => ["capture_peer_cert_chain" => true]]);
$h = stream_socket_client(
         "ssl://stackoverflow.com:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT,
         $context);
$params = stream_context_get_params($h);

$ca = null;

foreach ($params["options"]["ssl"]["peer_certificate_chain"] as $cert)
{
    openssl_x509_export($cert, $output);
    $ca .= $output;
}

file_put_contents("cafile", $ca);
Run Code Online (Sandbox Code Playgroud)

出口是:

$context = stream_context_create(["ssl" => ["cafile" => "cafile"]]);

file_get_contents("https://stackoverflow.com/", false, $context);
Run Code Online (Sandbox Code Playgroud)

一些背景:我使用来自https://curl.se/docs/caextract.html 的证书包。

出于某种原因,PHP 无法验证“USERTrust RSA Certification Authority”颁发的证书,尽管根证书似乎存在于捆绑包中。例如证书sectigo.com本身。这是我试图找到根本原因或解决方法的一部分。

on8*_*tom 4

stackoverflow仅提供服务器证书和中间ca证书。不是根 ca 证书。

openssl cafile 仅在完整链(到自签名根 ca)可以通过验证时才有效,

因此,您要么必须通过下载来信任根 CA,要么使用某种 pki,这样您就拥有所有全球受信任的根 CA。

在基于 Debian GNU / Linux 的机器上,您可以安装 ca-certificates 包, sudo apt-get install ca-certificates

或者您可以使用 mozilla 的 cacert https://curl.haxx.se/docs/caextract.html