An often heard solution to PHP cURL errors with SSL is to turn off
CURLOPT_SSL_VERIFYPEER. Please don’t turn off
CURLOPT_SSL_VERIFYPEER, but fix your PHP config instead. This article provides you with two solutions to solve CA certificate validation errors with PHP cURL and OpenSSL. For system administrators and end-users.
Here you’ll learn what you need to do to fix your PHP cURL configuration.
Don’t turn off CURLOPT_SSL_VERIFYPEER in your PHP config; fix cURL errors by updating cURL’s bundle of CA root certificates and your php.ini configuration.
When PHP cURL throws error messages like “
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed“, or “
SSL certificate problem, verify that the CA cert is OK“, cURL can’t validate a certificate’s CA. The error is often caused by an outdated or missing bundle of CA root certificates, in your PHP configuration.
This post provides two solutions to fix the CA validation with PHP cURL, and one for OpenSSL. For you, as system administrators and end-users.
Pádraic Brady writes:
[…] The options here are somewhat obvious, configuring PHP to use SSL properly is added complexity that programmers are tempted to ignore. Once you go down that road and once you start throwing user data into those connections, you have inherited a security vulnerability that poses a real risk to users. Perhaps more telling is the following function call using the cURL extension for HTTPS connections in place of PHP built-in feature.
This one is far worse than PHP’s default position since a programmer must deliberately disable peer verification in cURL. That’s blatantly the fault of the programmer and, yes, a lot of programmers do this. To deliberately disable SSL’s protection of user data, assuming it’s not due to ignorance, can only be described as loathsome and the tolerance afforded to such security vulnerabilities, at a time when browsers and Certificate Authorities would be publicly and universally condemned for the same thing, reflects extremely poorly on PHP programmers taking security seriously.
Seriously, do NOT do this. Yes, you’ll get more errors (browsers display big red warnings too). Yes, end programmers may need to define a path to a CA file. Yes, this is all extra work (and examples are scarce on the ground as to how to do it properly). No, it is NOT optional. Keeping user data secure outweighs any programming difficulty. Deal with it.
As you see, there’s a whole lot of misinformation about how to deal with these
SSL certificate problem, verify that the CA cert is OK errors with cURL. Nearly everyone advises you to turn off CURLOPT_SSL_VERIFYPEER, and in fact, countless comments on the PHP manual page for curl_setopt tell you to do this.
This is bad, because it allows your nice, encrypted stream of confidential data to be silently hijacked by a bad guy. So, don’t to that! Instead, fix your PHP php.ini configuration.
SSL certificate problem, verify that the CA cert is OK error is caused by not having an up-to-date bundle of CA root certificates, available to cURL, on your system. Not someone else’s.
The bundle of CA root certificates is typically an ordinary text file with cryptographic signatures. CURL uses this to verify a host’s SSL- or TLS certificate. Therefore you need to make sure that your PHP installation has one of these files, and that it’s up to date.
As a systems administrator,
To add a CA root certificates bundle in your
php.ini file, you (as systems administrator) need to download the
cacert.pem CA root certificate bundle from curl.haxx.se.
Then configure the path to this file in your
; Windows Server IIS: curl.cainfo = c:\path\to\php\cacert.pem ; Linux: ; curl.cainfo=/path/to/php/cacert.pem
As an end-user, read on to learn how you can easily fix the CA validation in cURL yourself. One of the errors caused by an outdated -or missing- bundle of CA root certificates is a WordPress Jetpack activation error.
What exactly are CA certificates?
CA certificates are all about trust. Certification authority (CA) certificates are certificates that are issued by a CA to itself or to a second CA for the purpose of creating a defined relationship between the two CAs. A certificate that is issued by a CA to itself is referred to as a trusted root certificate, because it is intended to establish a point of ultimate trust for a CA hierarchy.
Once the trusted root has been established, it can be used to authorize subordinate CAs to issue certificates on its behalf. Although the relationship between CAs is most commonly hierarchical, CA certificates are also used to establish trust relationships between CAs in two different public key infrastructure (PKI) hierarchies.
In all of these cases, the CA certificate is critical to defining the certificate path and usage restrictions for all end entity certificates issued for use in the PKI.
Fix Jetpack register_http_request_failed errors: How to register and activate Jetpack with WordPress properly!
One often reported error message is with activating the Jetpack plugin in WordPress. The error is:
Jetpack could not contact WordPress.com: register_http_request_failed. This usually means something is incorrectly configured on your web host. SSL certificate problem: self signed certificate in certificate chain
As a solution, you often read about turning off
CURLOPT_SSL_VERIFYPEER a lot. Well, don’t do that! In fact, don’t do this ever!
You can easily overcome and resolve this error by manually editing a line in
/wp-includes/class-http.php, if your web host is unable or unwilling to update the cURL root certificates (
cacert.pem file). Point your web host to this blog post for information.
First you need to download an up to date bundle of CA root certificates.
Here is how to fix
"Jetpack could not contact WordPress.com: register_http_request_failed. This usually means something is incorrectly configured on your web host." in just a few steps, and you are to able to connect the Jetpack plugin activation:
cacert.pem file(http://curl.haxx.se/ca/cacert.pem) to your computer
cacert.pemto your website, preferably to an unwritable location (but readable for the web server, just to protect the file)
function request()of class
curl_setopt( $handle, CURLOPT_CAINFO, "/path/to/domain/cacert.pem" );
Jetpack is now able to connect to WordPress!
sslverify = false for
wp_remote_get() in WordPress!
The default CA bundle may be overridden on a global basis by setting either the
openssl.capath configuration setting, or on a per request basis by using the cafile or capath context options.
For OpenSSL, you have to configure an
openssl.cafile path in your PHP installation as well:
[openssl] ; The location of a Certificate Authority (CA) file on the local filesystem ; to use when verifying the identity of SSL/TLS peers. Most users should ; not specify a value for this directive as PHP will attempt to use the ; OS-managed cert stores in its absence. If specified, this value may still ; be overridden on a per-stream basis via the "cafile" SSL stream context ; option. openssl.cafile=c:\php70\cacert.pem ; ; Linux: ; openssl.cafile=/path/to/cafile
This fixes WordPress errors you get with the WordPress HTTP API like
SSL certificate problem: unable to get local issuer certificate.. See Developers: Stop Using sslverify = false @SkyVerge for more information. My colleague Pieter also runs a post urging developers not to set sslverify to false.
If you want to step in to help me cover the costs for running this website, that would be awesome. Just use this link to donate a cup of coffee ($5 USD for example). And please share the love and help others make use of this website. Thank you very much!
My name is Jan. I am not a hacker, coder, developer, programmer or guru. I am merely a system administrator, doing my daily thing at Vevida in the Netherlands. With over 15 years of experience, my specialties include Windows Server, IIS, Linux (CentOS, Debian), security, PHP, websites & optimization.
Fatal error: Uncaught Error:  operator not supported for strings – PHP 7.1
Always_populate_raw_post_data setting in PHP 5.6 & Magento 2.0
Send authenticated email over TLS from Zen Cart
PHP 5.6 default_charset change may break HTML output
PHP, MySQL and IPv6: still slow
Convert PHP ext/mysql to MySQLi