使用PHP在Curl中将.PEM和.KEY作为字符串传递

5n0oy7gb  于 2022-11-13  发布在  PHP
关注(0)|答案(5)|浏览(195)

我有一个CERT和私钥文件。我使用cUrl和PHP连接到另一个服务。目前,我有文件中的证书和密钥,它可以很好地与以下代码一起工作:

$pemfile = "cert.pem";
$keyfile = "private_key.key";
$url = "someTestUrl";
$requestXml = "requestData";

$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_VERBOSE, 1); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); 
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1); 
curl_setopt($ch, CURLOPT_FAILONERROR, 1); 
curl_setopt($ch, CURLOPT_SSLCERT, $pemfile); 
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM'); 
curl_setopt($ch, CURLOPT_SSLKEY, $keyfile); 
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $requestXml);
$ret = curl_exec($ch);

我的问题是:我可以将cert和key作为字符串传递而不是作为文件传递吗?我尝试将各自文件的内容作为字符串传递,如下所示:

$pemfile = "-----BEGIN CERTIFICATE-----CERTDATAASSTRING-----END CERTIFICATE-----";
$keyfile = "-----BEGIN RSA PRIVATE KEY-----PRIVATEKEYINCODE-----END RSA PRIVATE KEY-----";

......不用说......它没有工作:(
有什么想法?指点?建议??

irlmq6kh

irlmq6kh1#

不幸的是,答案很简单:不,这是不可能的。
底层的libcurl实际上有一个API可以直接从内存中提供密钥和证书,但是PHP/CURL扩展只支持以文件的形式提供它们!

奖励材料:

如果您 * 确信 * libcurl是用OpenSSL构建的,那么您实际上可以使用CURLOPT_SSL_CTX_FUNCTION选项来实现。
1.这使它成为libcurl+OpenSSL特定的解决方案
1.我不认为PHP/CURL公开了这个函数(足够)来允许这样做。你可能需要首先扩展绑定代码...
(我应该补充一点,我是libcurl的主要作者和维护者。)

lx0bsm1f

lx0bsm1f2#

使用tmpfile()可能足以作为一种解决方法。

$tempPemFile = tmpfile();
fwrite($tempPemFile, $pemfile);
$tempPemPath = stream_get_meta_data($tempPemFile);
$tempPemPath = $tempPemPath['uri'];

然后:

curl_setopt($ch, CURLOPT_SSLCERT, $tempPemPath);

但请确保在此之后将其关闭,以便删除临时文件

fclose($tempPemFile);
gz5pxeao

gz5pxeao3#

您可以创建临时文件,将字符串写入文件,然后指向临时文件...

vu8f3i0k

vu8f3i0k4#

CURLOPT_SSLCERT_BLOB is now supported by PHP and the linked CURL它从PHP 8.1.0和cURL 7.71.0开始可用。
这意味着您可以将私钥作为memory/string传递
https://bugs.php.net/bug.php?id=81085是我如何发现的;它显然也有如何在单元测试中使用的示例
https://patch-diff.githubusercontent.com/raw/php/php-src/pull/7194.patch
基本上

$clientCert = file_get_contents($clientCertPathPEMFile);
$clientKey = file_get_contents($clientKeyPathPEMFile);

curl_setopt($ch, CURLOPT_SSLCERT_BLOB, $clientCert);
curl_setopt($ch, CURLOPT_SSLKEY_BLOB, $clientKey);
lmyy7pcs

lmyy7pcs5#

我不是SSLMaven,但CURLOPT_SSLKEY是CURLOPT_SSLCERT公共.pem文件的私有.pem文件?
我的参数

CURLOPT_CAINFO => /path/cacert.pem
CURLOPT_SSLKEY => /path/private.pem
CURLOPT_SSLCERT => /path/public.pem

试试我建议的答案,让我知道它是否有帮助。

相关问题