【问题标题】:cURL: CURLOPT_CAPATH contains correct cert but doesn't workcURL:CURLOPT_CAPATH 包含正确的证书但不起作用
【发布时间】:2017-01-03 14:44:14
【问题描述】:

以下脚本适用于PHP 5.6.23

$options = [
    CURLOPT_POST => 1,
    CURLOPT_URL => 'https://uat.dwolla.com/oauth/rest/offsitegateway/checkouts',
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_POSTFIELDS => json_encode(['name'=>'value']),
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_CAINFO => '/path/to/certs/GoDaddyRootCertificateAuthority-G2.crt',
];
$ch = curl_init();

curl_setopt_array($ch, $options);
if( ! $result = curl_exec($ch)) $err = curl_error($ch);
else $err = null;

curl_close($ch);

if($err) echo $err;
else print_r(json_decode($result,true));

我从 Dwolla 的支付 API 获得了预期的响应。为了使我的脚本更加动态,我尝试将其更改为引用托管我希望 cURL 信任的证书的目录。所以我把最后一个选项(CURLOPT_CAINFO)改成了:

CURLOPT_CAPATH => '/path/to/certs'

然而,这会破坏脚本并且没有建立连接;错误是:

SSL 证书问题:无法获取本地颁发者证书

我知道目录是正确的并且证书文件是有效的,因为原始脚本引用了同一目录中的证书。我希望cURL 扫描目录中的文件并找到它需要的证书,但这并没有发生。这是为什么呢?

【问题讨论】:

  • crt 重命名为test.crt 并重试。
  • @Hackerman 没有区别;它以第一种方式工作(使用CURLOPT_CAINFO)。第二种方式同样的错误(CURLOPT_CAPATH)。
  • @Hackerman 我认为如果证书是问题所在,那么 OP 中的原始脚本将不起作用(因为它会根据我已经使用的证书验证远程服务器)。我仍然尝试了您发送的证书,结果是一样的。原创剧本作品;修改后的脚本产生相同的错误
  • 刚刚尝试(使用 php.ini 配置)使用curl.capath(以及openssl.capath) - 两者都没有效果。但是使用openssl.cainfo 它可以工作。我不确定为什么capath 不起作用。

标签: php ssl curl


【解决方案1】:

如果您只是将 CApath 指向某个目录并将证书放入该目录,则它不起作用。为了有效地查找正确的 CA 证书,此目录中的文件需要具有从证书主题派生的名称。例如,您可能会在/etc/ssl/certs 中找到以下内容:

   ff783690.0 -> UTN_USERFirst_Hardware_Root_CA.pem
   ff588423.0 -> ComSign_CA.pem
   ...

这里的文件名基于证书主题的哈希值并指向真正的证书。有关如何创建必要文件名的信息,请参阅How to calculate the hash value used by CA file names

另见man page for openssl verify

-CApath目录
受信任证书的目录。证书应具有以下形式的名称:hash.0 或具有这种形式的符号链接(“hash”是散列的证书主题名称:请参阅 x509 实用程序的 -hash 选项)。在 Unix 下,c_rehash 脚本会自动创建指向证书目录的符号链接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-23
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-15
    相关资源
    最近更新 更多