cURL:CURLOPT_CAPATH包含正确的证书,但是不起作用

Bee*_*ice 5 php ssl curl

以下脚本适用于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));
Run Code Online (Sandbox Code Playgroud)

我从Dwolla的付款API得到了预期的响应。为了使脚本更具动态性,我尝试将其更改为引用托管我希望cURL信任的证书的目录。因此,我将最后一个选项(CURLOPT_CAINFO)更改为:

CURLOPT_CAPATH => '/path/to/certs'
Run Code Online (Sandbox Code Playgroud)

但是,这会破坏脚本,并且不会建立连接。错误是:

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

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

Ste*_*ich 5

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

   ff783690.0 -> UTN_USERFirst_Hardware_Root_CA.pem
   ff588423.0 -> ComSign_CA.pem
   ...
Run Code Online (Sandbox Code Playgroud)

这里的文件名基于证书主题的哈希值并指向真实证书。有关如何创建必要文件名的信息,请参阅如何计算 CA 文件名使用的哈希值

另请参阅openssl verify手册页

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