47

I am using curl to download data from a https site using public certificate files.

System information:

  • OS: fedora 14
  • curl: curl 7.30.0
  • openssl: OpenSSL 1.0.0a-fips

The command is,

curl -v "https://<ip:<port>" --cert "./cert.pem" --cacert "./cacert.pem" --cert-type PEM
* About to connect() to kng.com port 443 (#0)
*   Trying 11.19.37.123...
* Adding handle: conn: 0x8189e68
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x8189e68) send_pipe: 1, recv_pipe: 0
* Connected to fkng.com (11.19.37.123) port 443 (#0)
* unable to set private key file: './cert.pem' type PEM
* Closing connection 0
curl: (58) unable to set private key file: './cert.pem' type PEM

I have have given all the permission to the .pem file, still curl is throwing an error.

nwinkler
  • 52,665
  • 21
  • 154
  • 168
user1495372
  • 585
  • 2
  • 6
  • 13

5 Answers5

32

After reading cURL documentation on the options you used, it looks like the private key of certificate is not in the same file. If it is in different file, you need to mention it using --key file and supply passphrase.

So, please make sure that either cert.pem has private key (along with the certificate) or supply it using --key option.

Also, this documentation mentions that Note that this option assumes a "certificate" file that is the private key and the private certificate concatenated!

How they are concatenated? It is quite easy. Put them one after another in the same file.

You can get more help on this here.

I believe this might help you.

Peter Vandivier
  • 606
  • 1
  • 9
  • 31
doptimusprime
  • 9,115
  • 6
  • 52
  • 90
  • Thanks for your valuable information..Still one thing i dont understand is how can i retrieve private key from the public certificate. i can get public key "openssl x509 < testcert.pem -pubkey -noout" using this command ,and do the authentication with https url somthing like this ,curl "https://" --cert "./testcert.pem" --cacert "./cacert.pem" --pubkey "./testkey.pem" --cert-type PEM....When i hit this same url using mozill browser it is able to show me the same .pem file. – user1495372 May 18 '13 at 19:15
  • Public key certificate does not contain private key. Private key is to be securely kept by the owner. If you do not have private key, you are not the owner of the certificate. – doptimusprime May 18 '13 at 19:16
  • Actually this public certificate is given by another server to download the data from their https url..Is it possible to download the data using the public certificate from the https url.Incase if you give me your HTTPS url to download the data every time what are the credentials required to see https page content. – user1495372 May 18 '13 at 19:21
  • Is this certificate issued to your for a certificate signing request (CSR)? What is the purpose of this certificate? – doptimusprime May 18 '13 at 19:23
  • Then I think you may not require to use --cert parameter unless server is asking for the client certificate on connection. – doptimusprime May 18 '13 at 19:24
  • Actually without this --cert option when i use curl -v "https://" url i could not able to get the https page..i am getting connection refused error message.IS there any way to set curl to get https page as firefox able to get using only public certificate – user1495372 May 18 '13 at 19:32
  • 1
    If the connection is asking for the certificate, then it needs private key to sign the data by which server can verify that the certificate belongs to the client. If firefox able to use the certificate, it must have private key. You can export the private key and make use of it. – doptimusprime May 18 '13 at 19:38
  • But when open this url using firefox i can only able to get the public certificate from the "view certificate->Export" option.So can you please tel me, how to retrieve the private key from my browser. – user1495372 May 18 '13 at 19:45
  • For personal certificate, you can export with its public key into pfx format. – doptimusprime May 19 '13 at 01:36
  • May I ask why the private key should be specified? – Iulian Jun 18 '15 at 14:15
  • In case of Mutual SSL Authentication, when you need to send public key, you also need to send a data signed by private key so that receiver can confirm that this public key belongs to you. In such cases, private key is used for signing the data. – doptimusprime Jun 19 '15 at 02:39
16

I had the same issue, eventually I found a solution that works without splitting the file, by following Petter Ivarrson's answer

My problem was when converting .p12 certificate to .pem. I used:

openssl pkcs12 -in cert.p12 -out cert.pem

This converts and exports all certificates (CA + CLIENT) together with a private key into one file.

The problem was when I tried to verify if the hashes of certificate and key are matching by running:

// Get certificate HASH
openssl x509 -noout -modulus -in cert.pem | openssl md5

// Get private key HASH
openssl rsa -noout -modulus -in cert.pem | openssl md5

This displayed different hashes and that was the reason CURL failed. See here: https://michaelheap.com/curl-58-unable-to-set-private-key-file-server-key-type-pem/

I guess that was because all certificates are inside a file (CA + CLIENT) and CURL takes CA certificate instead of CLIENT one. Because CA is first in the list.

So the solution was to export only CLIENT certificate together with private key:

openssl pkcs12 -in cert.p12 -out cert.pem -clcerts
``

Now when I re-run the verification:
```sh
openssl x509 -noout -modulus -in cert.pem | openssl md5
openssl rsa -noout -modulus -in cert.pem | openssl md5

HASHES MATCHED !!!

So I was able to make a curl request by running

curl -ivk --cert ./cert.pem:KeyChoosenByMeWhenIrunOpenSSL https://thesite.com

without problems!!!

That being said... I think the best solution is to split the certificates into separate file and use them separately like Petter Ivarsson wrote:

curl --insecure --key key.pem --cacert ca.pem --cert client.pem:KeyChoosenByMeWhenIrunOpenSSL https://thesite.com
cure85
  • 441
  • 5
  • 6
15

I faced this issue when I had used Open SSL and the solution was to split the cert in 3 files and use all of them doing the call with Curl:

openssl pkcs12 -in mycert.p12 -out ca.pem -cacerts -nokeys
openssl pkcs12 -in mycert.p12 -out client.pem -clcerts -nokeys 
openssl pkcs12 -in mycert.p12 -out key.pem -nocerts

curl --insecure --key key.pem --cacert ca.pem --cert client.pem:KeyChoosenByMeWhenIrunOpenSSL https://thesite
Petter Ivarsson
  • 463
  • 6
  • 6
  • hmm. sure that its on the client.pem you set your password? – Philip Dec 05 '17 at 17:06
  • 4
    Dude, you used --insecure which means you are not actually using the .pem :| – ALUFTW Jul 25 '21 at 09:02
  • @ALUFTW `--insecure` disables verification of server certificates. It shouldn't affect client certificates, so client.pem is used. Though I guess the ca.pem is probably ignored when using --insecure – kapex Nov 09 '22 at 15:41
4

I have a similar situation, but I use the key and the certificate in different files.

in my case you can check the matching of the key and the lock by comparing the hashes (see https://michaelheap.com/curl-58-unable-to-set-private-key-file-server-key-type-pem/). This helped me to identify inconsistencies.

Andrey Batalov
  • 59
  • 1
  • 2
  • 6
2

Im not sure If this will help anyone but I was getting this error (although I was using php to create it instead of the command line) and to fix it I had to ensure that no old .key or .pem files were in the directory I was looking at. By deleting them and making fresh files with the authentication it worked perfectly!