【问题标题】:What exactly goes into CURLOPT_CAINFO/CAPATH?CURLOPT_CAINFO/CAPATH 到底是什么?
【发布时间】:2019-08-08 02:12:58
【问题描述】:

尝试使 PHP 中的 CURL 与自签名证书一起工作。我已经为客户端代码提供了证书文件的副本,并在CURLOPT_CAINFOCURLOPT_CAPATH 中指定了证书文件的路径。不过,我收到错误 60:SSL certificate problem: unable to get local issuer certificate


这里是重现步骤。全部在 Linux 上(在我的例子中是 Debian Stretch)。将 example.com 替换为相关的主机名。

首先,我会生成一个私钥:

openssl genrsa -out key.pem 2048

编写配置文件:

[req]
prompt=no
distinguished_name=dn
req_extensions=ext
x509_extensions=ext

[dn]
emailAddress=seva@example.com
CN=example.com
O=Seva Alekseyev
L=Chicago
ST=IL
C=US

[ext]
keyUsage=digitalSignature,keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt

[alt]
DNS=example.com

另存为req.txt,生成自签名证书:

openssl req -x509 -new -config req.txt -days 3650 -key key.pem -out example.cer

在 Apache 中以 example.com 的主机名安装 example.cerkey.pem。浏览以确保基本设置有效(以可怕的安全消息为模)。

现在,客户。将example.cer 的副本放在$path 下。 PHP 代码如下:

$cu = curl_init("https://example.com/");
curl_setopt_array($cu, array(
    CURLOPT_HEADER => false,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CAINFO => "$path/example.cer",
    CURLOPT_CAPATH => "$path/example.cer"
    ));
$r = curl_exec($cu);
$c = curl_errno($cu);
$s = curl_error($cu);
curl_close($cu);

echo "$c $s";

然后是错误信息。

我在这里缺少什么?一些指南建议 CURLOPT_CAINFO/CAPATH 的值应该是一个文件夹,而基于串行的符号链接指向证书文件。也试过了,同样的错误。 https://curl.haxx.se/docs/sslcerts.html 的文件说:

获取可以验证远程服务器的 CA 证书,并在连接时使用适当的选项指出此 CA 证书以进行验证。

但是那里没有 CA,没有证书链。签名证书本身。我是否应该以某种方式转换证书以便 CURL 将其视为 CA 证书?我应该先生成一个假 CA 证书,然后用那个证书签署 SSL 证书吗?


命令行 curl 和 curl --cacert example.cer https://example.com/ 一样,弹出相同的消息。


相关问题here,但我不想乱用系统范围的设置。

【问题讨论】:

    标签: php ssl curl ssl-certificate self-signed


    【解决方案1】:

    CURLOPT_CAINFO/CAPATH 指向的证书应该是 CA 证书 - 至少在使用 OpenSSL 时是这样。这意味着您的自签名证书也需要是 CA 证书,即它不仅应适用于 serverAuth,还应具有基本约束 CA:true

    【讨论】:

    • 补充说。 Basic Constraints 行现在变为:Subject Type=CA Path Length Constraint=None。同样的错误:(
    【解决方案2】:

    [ext] 下的keyUsage 行必须包含keyCertSign,如下所示:

    keyUsage=digitalSignature,keyEncipherment,keyCertSign
    

    否则,就 OpenSSL 而言,它不是 CA 证书。

    OBTW,[ext] 下的 basicConstraints=CA:true 行,由 Steffen 建议,不是必需的,我已经检查过了。至少 CURL 7.52.1 和 OpenSSL 1.0.2r 不是这样。

    在客户端代码中,CURLOPT_CAPATH 也不是必需的。 CURL 支持两种指定根 CA 证书包的替代方法。 CURLOPT_CAINFO 使 CURL 读取并解析单个文件,其中可能包含多个证书。 CURLOPT_CAPATH 使 CURL 扫描一个目录,其中包含由其序列号标识的证书文件 - 或指向这些文件的符号链接,由 c_rehash 生成。因为在我的场景中,有效的根 CA 证书包只有一个证书,所以一个文件方法就足够了。

    在 Windows 下不起作用,至少在命令行 CURL 7.55.1 下是这样。 Windows 版本的 CURL 使用内置的 Schannel 库来实现其 SSL,并忽略 --cacert 选项,而是依赖于 Windows 的内置可信 CA 存储。 See here.

    也许可以针对不同的 SSL 实现为 Windows 重建 CURL,但麻烦不值得。 Windows 带有自己的 HTTP(S) 客户端群。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-06
      • 2013-05-05
      • 2010-11-19
      • 2012-06-16
      • 2011-04-02
      • 2016-04-13
      • 2012-03-07
      • 2013-08-14
      相关资源
      最近更新 更多