简体   繁体   中英

Passing .PEM and .KEY as string in Curl using PHP

I've a CERT and private key files. I'm using cUrl and PHP to connect to another service. At the moment, I've cert and key in files and it works perfectly fine with following code:

$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);

My question is: Can I pass cert and key as strings rather passing them as files? I tried simply passing contents of respective files as strings like this:

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

...and needless to say...it didn't work:(

Any ideas? pointers? suggestions???

The answer is unfortunately as easy as it is simple: No, it is not possible.

The underlying libcurl has no API for providing keys as strings, only as files!

Bonus material:

If you're sure that your libcurl is built with OpenSSL, you can actually use the CURLOPT_SSL_CTX_FUNCTION option to do it. However:

  1. that makes it an libcurl+OpenSSL specific solution

  2. I don't think PHP/CURL exposes that function (enough) to allow this. You would probably need to extend the binding code first...

(I should add that I am the main author and maintainer of libcurl.)

Using tmpfile() might suffice as a workaround.

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

and then:

curl_setopt($ch, CURLOPT_SSLCERT, $tempPemPath); 

but make sure you close it after so the tmp file is delete

fclose($tempPemFile);

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

CURLOPT_SSLCERT_BLOB is now supported by PHP and the linked CURL It is available as of PHP 8.1.0 and cURL 7.71.0.

This mean you can pass private keys as memory/string

https://bugs.php.net/bug.php?id=81085 is how i found out; it obviously also has samples how to use, in the unit tests

https://patch-diff.githubusercontent.com/raw/php/php-src/pull/7194.patch

basically

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

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

I'm not SSL Expert but CURLOPT_SSLKEY is private.pem file of the CURLOPT_SSLCERT public.pem file?

My parameters

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

Try my suggested answer and let me know if it is helpful or not.

Let's say that you have the certificate text in $cert_in_text and KEY in the $key_text .

  1. I suggest using the tempnam() function to get the temporary filename.
  2. To avoid problems with accessing system's temp folder in restricted web-server environment, I suggest using the sys_get_temp_dir() function which will set temp directory from the php.ini of the current web server.
  3. Then write text contents of the certificate and the key to temporary file using the file_put_contents() function.
  4. To ensure that important information is removed from the file system, I suggest registering the later unlink() function call with the register_shutdown_function() .

Here is the example:

$tmpfile = tempnam(sys_get_temp_dir(),'');
file_put_contents($tmpfile, $cert_text);
register_shutdown_function('unlink',$tmpfile);

curl_setopt($ch, CURLOPT_SSLCERT, $tmpfile);

$tmpfile = tempnam(sys_get_temp_dir(),'');
file_put_contents($tmpfile, $key_text);
register_shutdown_function('unlink',$tmpfile);

curl_setopt($ch, CURLOPT_SSLKEY, $tmpfile);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM