How to force TLS v1.0 in PHP

PHP 5.6+ Users

This is a new feature as documented on the PHP 5.6 OpenSSL Changes page.

At time of writing this, PHP5.6 is in Beta1 and thus this isn’t overly useful. People of the future – lucky you!

Everyone Else

The title of this post isn’t strictly accurate as this isn’t possible in PHP < 5.6. However, when working around a problem where a supplier’s API server wasn’t correctly negotiating TLSv1.2 down to its supported TLSv1.0, sending a small subset of ciphers seemed to allow negotiation to complete correctly. This was done by setting some SSL options in the stream context.

I created a context passing it the set of permitted ciphers in CIPHERS(1) format. Code below:

  1. [
  2. 'ssl' => [
  3. 'ciphers' => 'DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:KRB5-DES-CBC3-MD5:KRB5-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:RC2-CBC-MD5:KRB5-RC4-MD5:KRB5-RC4-SHA:RC4-SHA:RC4-MD5:RC4-MD5:KRB5-DES-CBC-MD5:KRB5-DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:DES-CBC-MD5:EXP-KRB5-RC2-CBC-MD5:EXP-KRB5-DES-CBC-MD5:EXP-KRB5-RC2-CBC-SHA:EXP-KRB5-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-KRB5-RC4-MD5:EXP-KRB5-RC4-SHA:EXP-RC4-MD5:EXP-RC4-MD5',
  4. ],
  5. ]
  6. );

 

In a lot of cases, you can just use stream_context_set_default to set this info into the default stream context.

Special Note for SOAP Users

PHP’s SOAP client doesn’t seem to use the default stream context. As such, assign a stream context handle to a variable, as demonstrated above and pass this as a parameter to the SOAPClient constructor:

  1. $soap_client = new SOAPClient('http://webservices.site.com/wsdlfile.wsdl', array('stream_context' => $context));

Ciphers

The list of ciphers above came from OpenSSL‘s supported cipher list on the server in question. The command openssl ciphers -v will give you all of the supported ciphers and which crypto protocols they apply to. I filtered out TLSv1.2 and passed this list to the stream_context_create in the above example.

The following shell command should give you what you require:

  1. openssl ciphers -v | grep -v 'TLSv1.2' | cut -d ' ' -f 1 | tr "\n" ':'

 

5 comments

  1. Thx, tips save my day !

    Added this on top of a script that connect to a bug https server:
    $context = stream_context_set_default(
    [
    'ssl' => [
    'ciphers' => 'DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:KRB5-DES-CBC3-MD5:KRB5-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:RC2-CBC-MD5:KRB5-RC4-MD5:KRB5-RC4-SHA:RC4-SHA:RC4-MD5:RC4-MD5:KRB5-DES-CBC-MD5:KRB5-DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:DES-CBC-MD5:EXP-KRB5-RC2-CBC-MD5:EXP-KRB5-DES-CBC-MD5:EXP-KRB5-RC2-CBC-SHA:EXP-KRB5-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-KRB5-RC4-MD5:EXP-KRB5-RC4-SHA:EXP-RC4-MD5:EXP-RC4-MD5',
    ],
    ]
    );

  2. Thanks for this useful tip. It works also for HTTPS proxi with apache by using the SSLProxyProtocol directive.

    http –> | Proxy | –> https (TLSv1.0)

    I dug for 3 days with this issue. I thought I was going crazy.

  3. Rénald Casagraude

    You may also specify “TLSv1” in the ciphers list as stated in:
    http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT

    Also, keep in mind that the support for TLS is somewhat broken in php-5.4.33:
    https://bugs.php.net/bug.php?id=41631

  4. Ricardo Fontanelli

    Thanks for this tip, it save me!

  5. Thanks! Good job!

Leave a Reply

Your email address will not be published. Required fields are marked *