Using Curl in PHP with Client Certificate and Private Key in Separate Files

Using curl in php with client certificate and private key in separate files

Here is a PHP script with a literal translation of your command line call:

<?php

$data = "var1=value1&var2=value2&...";
$url = "https://www.somesite.com/page";

$keyFile = "key.pem";
$caFile = "ca.pem";
$certFile = "client.pem";
$certPass = "xxxxxx";

// Initialise cURL
$ch = curl_init($actualUrl);

// The -d option is equivalent to CURLOPT_POSTFIELDS. But...
// PHP's libcurl interface does not implement the -G flag - instead you would
// append $data to $url like this:
$actualUrl = $url.'?'.$data;
curl_setopt($ch, CURLOPT_URL, $actualUrl);

// The -v flag only makes sense at the command line, but it can be enabled
// with CURLOPT_VERBOSE - in this case the information will be written to
// STDERR, or the file specified by CURLOPT_STDERR. I will ignore this for
// now, but if you would like a demonstration let me know.

// The --key option - If your key file has a password, you will need to set
// this with CURLOPT_SSLKEYPASSWD
curl_setopt($ch, CURLOPT_SSLKEY, $keyFile);

// The --cacert option
curl_setopt($ch, CURLOPT_CAINFO, $caFile);

// The --cert option
curl_setopt($ch, CURLOPT_SSLCERT, $certFile);
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $certPass);

/*
Now we should get an identical request to the one created by your command
line string, let's have a look at some of the other options you set...
*/

// CURLOPT_HEADER is disabled by default, there's no need for this unless you
// enabled it earlier
//curl_setopt($ch, CURLOPT_HEADER, 0);

// Your command line string forces a GET request with the -G option, are you
// trying to POST or GET?
//curl_setopt($ch, CURLOPT_POST, true);

// We don't need body data with a GET request
//curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

// Since we've gone to all the trouble of supplying CS information, we might
// as well validate it!
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

What means --key in cUrl

You are not sending your private key to the server. The key is used so that server can verify that client certificate you are providing, was indeed issued to you and you posses the corresponding private key. It's used to sign a piece of data that was sent by server. Only this signed data is transmitted not the key. Server then uses your certificate (which was signed by CA trusted by server) to decrypt data and confirm you are in a possesion of the corresponding private key. (for more on how TLS checks client certificate during TLS handshake see this answer or this shorter one one)

This is similar to how you need to provide, usually PKCS#12 file, to your browser, in order to access web pages that require client certificate authentication. The PCKS#12 is an archive format that contains bundled certificate and private key. curl allows you to use this format in --cert option as well, from man page:

-E, --cert <certificate[:password]>

(TLS) Tells curl to use the specified client certificate file when getting a file with HTTPS, FTPS or another SSL-based protocol. The certificate must be in PKCS#12 format if using Secure Transport, or PEM format if
using any other engine.

cURL unable to use client certificate (no key found or wrong pass phrase?)

Solved with cURL.

The problem was the path of the pem file.

I was using base_url() . 'public/cert.pem' but that's not possible. Instead I need to use a relative path such as ./public/cert.pem.

unable to use client certificate(no key found or wrong pass phrase?)

Found the Solution. It required an intermediate CA Certificate.

The Solution is

$options = [
CURLOPT_HTTPHEADER => ['Content-type: application/json'],
CURLOPT_URL => 'https://address/to/service?param=value',
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_CAINFO => getcwd()."\cacert.pem",
URLOPT_SSLCERT => getcwd().'\cert.pem',
CURLOPT_SSLCERTPASSWD => 'ssl_password',
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_USERPWD => $soapUser.":".$soapPassword,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $data
];

$ch = curl_init();
curl_setopt_array($ch , $options);
$response = curl_exec($ch);

if (curl_errno($ch)) {
print curl_error($ch);
}else{
print_r($response);
}

curl_close($ch);

Do not forget to mention the CURLOPT_HTTPHEADER to its content type, it is important.

Also download the intermediate certificate from https://curl.haxx.se/ca/cacert.pem. It contains all the valid CA's.

Thanks @drew010 for help.

SSL Client Authentication using PHP

The CURLOPT_SSLCERT option allows you to specify the path to your certificate.



Related Topics



Leave a reply



Submit