SSL error SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

The Solution to SSL error SSL3_GET_SERVER_CERTIFICATE:certificate verify failed is


The file that you downloaded (http://curl.haxx.se/ca/cacert.pem) is a bundle of the root certificates from the major trusted certificate authorities. You said that the remote host has a self-signed SSL certificate, so it didn't use a trusted certificate. The openssl.cafile setting needs to point to the CA certificate that was used to sign the SSL certificate on the remote host. PHP 5.6 has been improved over previous versions of PHP to now verify peer certificates and host names by default (http://php.net/manual/en/migration56.openssl.php)

You'll need to locate the CA certificate that was generated on the server that signed the SSL certificate and copy it to this server. The only other option is to disable verifying the peer, but that defeats the SSL security. If you DO want to try disabling verification, try this array with the code from my previous answer:

$contextOptions = array(
    'ssl' => array(
        'verify_peer' => false,
        'verify_peer_name' => false
    )
);

Either way, if you're using self-signed certificates, you'll need to add the CA cert that was used to sign the remote host's SSL certificate to the trusted store on the server you're connecting from OR use stream contexts to use that certificate for each individual request. Adding it to the trusted certificates is the simplest solution. Just add the contents of the remote host's CA cert to the end of the cacert.pem file you downloaded.

Previous:

fsockopen doesn't support stream contexts, so use stream_socket_client instead. It returns a resource that can be used with all the commands that fsockopen resources can.

This should be a drop in replacement for the snippet you have in your question:

<?php

$contextOptions = array(
    'ssl' => array(
        'verify_peer' => true, // You could skip all of the trouble by changing this to false, but it's WAY uncool for security reasons.
        'cafile' => '/etc/ssl/certs/cacert.pem',
        'CN_match' => 'example.com', // Change this to your certificates Common Name (or just comment this line out if not needed)
        'ciphers' => 'HIGH:!SSLv2:!SSLv3',
        'disable_compression' => true,
    )
);

$context = stream_context_create($contextOptions);

$fp = stream_socket_client("tcp://{$host}:{$port}", $errno, $errstr, 20, STREAM_CLIENT_CONNECT, $context);

if (!$fp) {

    echo "$errstr ({$errno})<br />\n";

}else{

    $this->request = 'POST '.substr($this->url, strlen($this->host)).' HTTP/1.1'.$crlf
        .'Host: '.$this->host.$crlf
        .'Content-Length: '.$content_length.$crlf
        .'Connection: Close'.$crlf.$crlf
        .$body;

    fwrite($fp, $this->request);

    while (!feof($fp)) {
        $this->response .= fgets($fp);
    }

    fclose($fp);

}

~ Answered on 2015-09-03 02:57:00


Most Viewed Questions: