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

时间:2016-08-26 21:00:05

标签: 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));

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

CURLOPT_CAPATH => '/path/to/certs'

但是这会破坏脚本并且没有连接;错误是:

  

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

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

1 个答案:

答案 0 :(得分:4)

如果您只是将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脚本将自动创建指向证书目录的符号链接。