PayPal SSL upgrade to TLS 1.2 and HTTP/1.1

PayPal have committed to a longer signing key length and part of this is in the need to upgrade your SSL and CURL stack to support TLS 1.2 and HTTP/1.1, this will hit most people via the IPN acknowledgement call back.

Why the longer key length? Basically over time the ability of computers to ‘crack’ a given key length in a reasonable length of time becomes more and more likely – increasing the key length is a simple way of keeping one step ahead of faster computers and the rate of technology development.

Now I had to make this  change on our servers (RedHat) and found an interesting problem, by default the curl & Php versions shipped do not default to TLS 1.2 – you need to give it a ‘kick’ to do that. i.e.

php -r '$ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://tlstest.paypal.com/"); var_dump(curl_exec($ch)); var_dump(curl_error($ch));'

will fail for you, returning

bool(false)
string(17) "SSL connect error"'

yet if you do:

php -r '$ch = curl_init(); curl_setopt($ch, CURLOPT_SSLVERSION, 6); curl_setopt($ch, CURLOPT_URL, "https://tlstest.paypal.com/"); var_dump(curl_exec($ch)); var_dump(curl_error($ch));'

you will see

PayPal_Connection_OKbool(true)

Therefore to cover all bases going forwards ensure when you have strict SSL usage in Curl always explicitly set the SSL version to 6 for the PayPal API’s. This also saves you having to upgrade your whole Php stack to get the default change…

 

Note: you also need to ensure you have the latest certificates installed. The following script below will show you if you are ready to roll:

#!/bin/bash
echo "All certificates in ca-certificates.crt, listed by subject:"
awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' < /etc/pki/tls/certs/ca-bundle.crt
echo "All certificates in ca-certificates.crt, listed by subject, check for presence of VeriSign's 'Class 3 Public Primary - G5':"
awk -v cmd='openssl x509 -noout -subject' '/BEGIN/{close(cmd)};{print | cmd}' < /etc/pki/tls/certs/ca-bundle.crt | grep "G5"

If you see

subject= /C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5

then you are good to go, otherwise you need to do a yum update to pull in the latest.

WooCommerce IPN SSL Problems on WordPress

You may find in your WooCommerce logs you get a SSL Error popping up, this is because of the above change. If your site operates in an environment not yet upgraded, there is a little ‘hack’ you can do to WordPress directly. If you have edit access into your hosting, navigate to the file wp-includes/class-wp-http-curl.php and around line 131 you will see:

 curl_setopt( $handle, CURLOPT_URL, $url); 
 curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); 
 curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, ( $ssl_verify === true ) ? 2 : false ); 
 curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, $ssl_verify ); 

Add the following line to the bottom.

curl_setopt( $handle, CURLOPT_SSLVERSION, 6 );

So you end up with:

 curl_setopt( $handle, CURLOPT_URL, $url); 
 curl_setopt( $handle, CURLOPT_RETURNTRANSFER, true ); 
 curl_setopt( $handle, CURLOPT_SSL_VERIFYHOST, ( $ssl_verify === true ) ? 2 : false ); 
 curl_setopt( $handle, CURLOPT_SSL_VERIFYPEER, $ssl_verify ); 
 curl_setopt( $handle, CURLOPT_SSLVERSION, 6 );

This is quick and dirty – there is a hook ‘http_api_curl’ that could be used later on to set this (with a global switch to enable only for this usage), I’ll leave that to the WooCommerce developers to look at.