I've spent a few hours trying to get cURL (in PHP) to work with the Swedish BankID service, and running into the following two certificate errors:
CURL ERROR 60: SSL certificate problem: unable to get local issuer certificate
CURL ERROR 77: error setting certificate verify locations:
CAfile: C:\test\bankid\bankid_test_server.pem
CApath: C:\test\bankid\bankid_test_server.pem
The code I'm using to initialize cURL is the following:
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, getcwd().DIRECTORY_SEPARATOR.$bankidServerCertFile);
curl_setopt($ch, CURLOPT_CAPATH, getcwd().DIRECTORY_SEPARATOR.$bankidServerCertFile);
curl_setopt($ch, CURLOPT_SSLCERT, $clientCertFile);
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $clientCertPass);
curl_setopt($ch, CURLOPT_SSLKEY, $clientCertKeyFile);
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $clientCertKeyPass);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
I've tried various variations of the CURLOPT_CAINFO
and CURLOPT_CAPATH
options, but I still get either of the two errors (when I try some variations of the options I get one, when I try some other variations I get the other error).
I got the server certificate by following the advice to export it using Firefox, as described in this SO question. The certificate file is in the correct location and readable.
It turns out the problem was the content of the certificate file itself.
First, exporting it using Firefox doesn't give you the correct certificate. It should be downloaded from the BankID integrations guide. Look under the expanding header Issuer of server certificate
in either the Production environment
or Test environment
sections, and copy the actual certificate string starting with
-----BEGIN CERTIFICATE-----
and ending with
-----END CERTIFICATE-----
(including the starting- and ending lines).
Second, that still won't work with cURL if you just paste it in a text file as it is. It seems that it needs to be formatted in a certain way, more precisely broken down into 64 character long lines.
You can use an online tool, such as samltool.com - Format a X.509 certificate to do this. Paste the text you copied into the field X.509 cert
, press Format X.509 certificate
, then copy the text from the field X.509 cert with header
. Paste this into the certificate file on your server (in my case C:\test\bankid\bankid_test_server.pem
). The file should now start with
-----BEGIN CERTIFICATE-----
followed by a bunch of 64 character long lines, and ending with
-----END CERTIFICATE-----
If it still doesn't work, make sure that the path to the certificate file is correct, that it is readable by PHP and that you copied the correct (production/test) certificate depending on if you're calling the test- or production URL's.