file_get_contents(): SSL operation failed with code 1 certificate verify failed

I got this error when I moved a site to new server. It was a simple file_get_contents() call to read an image file. If i copy pasted the url of the same file to open in browser it would open just fine but the script would just die for the error similar to the one below.

file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

The first solution I found at stackoverlow was to just to disable the warning by doing this:

$options = [
    "ssl" => [
        "verify_peer"=>false,
        "verify_peer_name"=>false,
    ]
];  

$response = file_get_contents("https://www.example.com/image.jpg", false, stream_context_create($options));

Eventually, this is okay, only if you are working in development environment where you simply want to just to do coding and testing and don’t care about security or other serious stuff.

The second and more accurate solution was to do the following:

$options = [
    "ssl"=> [
    "cafile" => "/path/to/bundle/cacert.pem",
    "verify_peer"=> true,
    "verify_peer_name"=> true,
    ],
];  

$response = file_get_contents("https://www.example.com/image.jpg", false, stream_context_create($options));

Here, contrary and rightly, to turning off the SSL verification you specify the certificate bundle file full path as another parameter to $options array passed to stream_context_create() function as third argument.

Although this second method works quite well it has its own limitations. The first problem here is defining SSL certificate path which might vary. It could be sensitive to reveal this path. Another issue is with passing $options for each and every call to file_get_contents() function. It becomes tedious where you have an application already coded and there are many such calls already in place you may not be in position to perform ‘just change right now thing’.

The third and so called complete solution is to specify the certificate path in you php.ini file as another option in there. This option is named as openssl.cafile= and found in [openssl] section of your php.ini file. I assume you have SSH access to your server. So, set here the value of option openssl.cafile equal to the full path of your SSL certificate file, as below.

openssl.cafile=/path/to/cacert.pem

Once you edit and save the the php.ini file, restart your webserver and try it again. If your certificate is good and bundled correctly this should be it!

Using public certification

NOTE: Please not that as a solution to this problems a kind of public SSL certificate i.e. https://curl.haxx.se/ca/cacert.pem has been recommended. I downloaded and tried this certificate but it didn’t work. I had to bundle my own certificate in order to make it work. So check your options, maybe it works for some hosts or environments but I am not sure.

Remember that this warning occurs only when you try to read a file through secure tag in your request i.e. https://. It in fact tries to verify your internal https requests which is good for your own. This is similar to what browser does for you by parsing SSL files to verify.

Another thought just came into my mind is that this kind of issue may occur where your certificate is installed correctly but it is not bundled into full chained SSL. Browser might parse these chunked files to verify the full chain but when you do it through your php script it is not able to parse it to create full chain. I had installed the certificate by placing those in VESTACP user interface in form of one main pem file and another PSCK7 file.

Additional things I had to do

I had one certificate file which began with old “—–BEGIN CERTIFICATE—–“

Another file which i had was one which began with “—–BEGIN PKCS7—–“

So the first step is to convert PKCS7 into pem or actually certificate file. Here is the command

openssl pkcs7 -print_certs -in pkcs7-file.p7b -out certificates1.pem

Next step is to concatenate both certificate files into. My main certificate.pem and second bundle certificates1.pem will be joined into one file. You can do it by copying the contents of first file into a new .pem file and then copy paste contents of second file into the same new file and so on. You may have more certificate files to be joined into one so please check your certificate company you are provided certificate by.

Here is my quick way to combine two certificate into one

cat certificate.pem certificates1.pem > certificate-bundle.pem

Leave a Reply