Unable to use libcurl to access a site requiring client authentication
Asked Answered
K

4

6

I’m using the below snipped for setting the certificate and key for client authentication.

  curl_easy_setopt(curl,CURLOPT_SSLCERT,"clientCert.pem");
  curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD,"changeit");
  curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
  curl_easy_setopt(curl,CURLOPT_SSLKEY,"privateKey.pem");
  curl_easy_setopt(curl,CURLOPT_SSLKEYPASSWD,"changeit");
  curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,"PEM");

The certificate doesn’t have a password, I don’t know why on earth the option SSLCERTPASSWD exists, I just provided a dummy value. When I run the program on Linux I get an error code of 58 and an error message unable to set private key file: 'privateKey.pem' type PEM

On Windows however I get unable to use client certificate (no key found or wrong pass phrase?)

It seems to suggest the certificate and the key don’t match but I don’t know how. I have extracted both the cert and the key from a p12 file using openssl commands. The command I used to extract the key is

openssl.exe pkcs12 -in client.p12 -nocerts -out privateKey.pem

and the command used to extract the cert is

openssl.exe pkcs12 -in client.p12 -nokeys -out clientCert.pem

The p12 file has been successfully used in a browser to access the client authentication url. Please help before I shoot myself.

Edit: Here is proof that the private key and the certificate correspond to each other:

[debugbld@nagara ~/curlm]$ openssl x509 -noout -modulus -in clientCert.pem | openssl md5
d7207cf82b771251471672dd54c59927

[debugbld@nagara ~/curlm]$ openssl rsa -noout -modulus -in privateKey.pem | openssl md5
Enter pass phrase for privateKey.pem:
d7207cf82b771251471672dd54c59927

So why can’t it work?

Kalbli answered 25/5, 2011 at 12:13 Comment(1)
I'm facing the same result with the command line curl. I concatenated the client certificate and key into a file and tried as below: curl --cert concatenatedCert.pem --cert-type PEM --cacert cabundle.crt inaveo:8775/DataIntegrationService/WebService/WS_test Enter PEM pass phrase: curl: (58) unable to set private key file: 'concatenatedCert.pem' type PEMKalbli
P
3

Using the command line curl, I've got the same error using a .pem file that was also obtained with openssl from a p12 file, The p12 was also able to working properly doing client authentication when imported in a browser. Just like you described, I think.

My problem was caused because the .pem file was not listing the certificates in the proper order: seems that each certificate in the file has to be followed by its issuer certificate. I edited the file and changed the order of the sections and curl was happy.

For the record, my original .p12 file was obtained by backing up a certificate from Firefox.

Also note that in my case, I was not getting prompted for the password and was getting the

curl: (58) unable to set private key file: 'alice.pem' type PEM

before the password prompt

Philemon answered 11/11, 2011 at 19:7 Comment(0)
T
3

I was facing similar issues, I found out the problem was related to file permissions of the certificate and private key files. The process running PHP did not have read access to those files.

One thing you can try (and that helped me figuring this out) is to run the following code:

$result=openssl_get_privatekey('file://path/to/private/key.pem','password');

and check if the returned value is not false and there are no errors. I was getting:

file_get_contents(/path/to/private/key.pem): failed to open stream: Permission denied
Tribade answered 10/12, 2011 at 5:11 Comment(0)
P
1

Thanks Hugh for the thread and raugfer for the openssl hint. The later: both helpful and misleading. ;-)

Actually, I solved the problem by making sure that the path of the key file is correct. And here is why the openssl hint was misleading, dispite helping me to check if my PEM file was ok:

cURL needs the complete path, but without 'file://' prefix. While fopen is happy with a relative path, cURL is not. So, all my tests to open the key file had been successful, while cURL was not.

Btw.:

curl_easy_setopt(curl,CURLOPT_SSLCERTPASSWD,"changeit");
curl_easy_setopt(curl,CURLOPT_SSLCERTTYPE,"PEM");
curl_easy_setopt(curl,CURLOPT_SSLKEYTYPE,"PEM");

are not needed, as the password is only used to decrypt the private key and PEM is the default.

Pamphlet answered 27/2, 2013 at 18:27 Comment(0)
C
1

$result=openssl_get_privatekey('file://path/to/private/key.pem','password');

format for unix absolute paths is file:///path/to/private/key.pem',.... (three slashes)

format for Windows is 'file://C:\path\to\private\key.pem',....

Caracul answered 29/2, 2024 at 15:20 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.