How to add ciphers to curl in php?
Asked Answered
F

4

6

I am trying to use php curl to connect to a site, but get the error "no common encryption algorithm". Further investigation, and I think this has something to do with NSS? I've discovered that from the command line, I can reproduce the error (so the problem is definitely in curl and not with the php wrapper), but that if I set --ciphers ecdhe_ecdsa_aes_128_sha then it works:

[ec2-user@ip-10-181-165-22 current]$ curl -I https://sslspdy.com
curl: (35) Cannot communicate securely with peer: no common encryption algorithm(s).

[ec2-user@ip-10-181-165-22 current]$ curl -I --ciphers ecdhe_ecdsa_aes_128_sha https://sslspdy.com
HTTP/1.1 200 OK
Server: nginx centminmod
Content-Type: text/html; charset=utf-8
Connection: close
Vary: Accept-Encoding
Strict-Transport-Security: max-age=31536000; includeSubdomains
Date: Sat, 07 Feb 1970 22:34:32 GMT
X-Page-Speed: ngx_pagespeed
Cache-Control: max-age=0, no-cache

So my questions are,

  1. Why is this happening? I have not been able to find an explanation online as to how the ssl ciphers work in curl; it seems that every page is written with the assumption that the reader is already an expert in the field - unfortunately, a sentence like "you're probably using NSS, so try switching the PKCS for FIPS" is utterly incomprehensible to me, and googling will only explain the individual components (usually by reference to 20-year old standards), and not how they relate to each other.

  2. Is there any way I can make curl tell me which ciphers it is trying and which ciphers the server will accept? I've tried looking up the server on ssllabs, but it seems to be saying the server accepts all ciphers, which it obviously doesn't.

  3. What options do I need to pass to curl_setopt so that my php script is able to connect to this server?

  4. If I set the cipher to this, will that break other sites? Is there something I can do so that curl is able to connect to all secure sites, or do I have to manually iterate over different ciphers trying each of them to find out which one works?

Frye answered 5/6, 2015 at 11:14 Comment(0)
E
4
  1. Why is this happening? I have not been able to find an explanation online as to how the ssl ciphers work in curl

It depends on a few things. The client and server libraries, the client and server configurations, etc. You'd need to provide more details.


  1. Is there any way I can make curl tell me which ciphers

Use the right tool for the job. In this case, its an updated sslscan.


  1. What options do I need to pass to curl_setopt so that my php script is able to connect to this server?

CURLOPT_SSL_CIPHER_LIST.


  1. If I set the cipher to this, will that break other sites?

Maybe. It depends on that particular site's configuration.

Ideally, you pick 12 or 16 cipher suites you approve of, and then you use them instead of one. The 12 or 16 covers most sites you encounter on the internet.

Here's the list I usually use. Its from Which Cipher Suites to enable for SSL Socket?:

  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
  • TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_DHE_DSS_WITH_AES_128_CBC_SHA
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA

I would like to ditch the TLS_RSA_* cipher suites because they are key transport, but I need them for those older IIS servers I encounter.

As you can see from the scan results below, this list intersects with the server's list.


Note that you don't specify, say TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384. Rather, in OpenSSL, you specify the OpenSSL's name ECDHE-ECDSA-AES256-SHA384 for the suite. You can find the OpenSSL names at the documentation for openssl ciphers.

With OpenSSL, you can also use the string "HIGH:!aNULL:!MD5:!RC4:!PSK:!SRP". That will get you about 40 or 50 that are reasonably good choices.

You can run the OpenSSL ciphers command to see what the list is:

$ openssl ciphers -v 'HIGH:!aNULL:!MD5:!RC4:!PSK:!SRP'
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA384
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA384
ECDHE-RSA-AES256-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-ECDSA-AES256-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA1
...

You can use an updated version of sslscan to determine what cipher suites are available:

$ sslscan --no-failed sslspdy.com
...
Testing SSL server sslspdy.com on port 443

  Supported Server Cipher(s):
    Accepted  TLSv1  256 bits  ECDHE-ECDSA-AES256-SHA
    Accepted  TLSv1  128 bits  ECDHE-ECDSA-AES128-SHA
    Accepted  TLSv1.1  256 bits  ECDHE-ECDSA-AES256-SHA
    Accepted  TLSv1.1  128 bits  ECDHE-ECDSA-AES128-SHA
    Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-GCM-SHA384
    Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-SHA384
    Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-SHA
    Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-GCM-SHA256
    Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-SHA256
    Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-SHA

  Prefered Server Cipher(s):
    TLSv1  128 bits  ECDHE-ECDSA-AES128-SHA
    TLSv1.1  128 bits  ECDHE-ECDSA-AES128-SHA
    TLSv1.2  128 bits  ECDHE-ECDSA-AES128-GCM-SHA256
Ebonyeboracum answered 5/6, 2015 at 11:36 Comment(1)
That's great for showing what ciphers the server supports. But we need to know what ciphers curl supports. And the names used by curl in --ciphers are different. For instance, a particular router requires what openssl calls TLS_RSA_WITH_AES_256_CBC_SHA - but that doesn't work with curl.Kesselring
S
3

I have not been able to find an explanation online as to how the ssl ciphers work in curl;...

This is not specific to curl. With SSL/TLS the client offers the ciphers it is willing to use and the server picks from these a cipher which it supports too. By default clients don't offer all ciphers they can, especially not ciphers which are considered to weak.

Is there any way I can make curl tell me which ciphers it is trying and which ciphers the server will accept?

With wireshark you can see which ciphers are offered by the client. You can also check your client against https://www.ssllabs.com/ssltest/viewMyClient.html which shows which ciphers are offered. Or create a test server with openssl s_server -cipher ALL -www and connect the client to it, it will show the ciphers shared by client and server.

What options do I need to pass to curl_setopt...

CURLOPT_SSL_CIPHER_LIST with a value of ECDHE-ECDSA-AES128-SHA might work in your case. But this value actually depends on how your curl was compiled. Curl supports different SSL/TLS backends like OpenSSL, NSS, SecureTransport, SChannel, GnuTLS and the exact syntax depend on the backend. This example setting is valid for OpenSSL backend.

If I set the cipher to this, will that break other sites? ...

If you restrict yourself globally to this set then yes. For global settings you better add others too, i.e. HIGH:ECDHE-ECDSA-AES128-SHA:!aNULL. Bug again, the exact syntax depends on the SSL/TLS backend.

Schoolmarm answered 5/6, 2015 at 11:30 Comment(0)
F
2

Use curl_setopt with CURLOPT_SSL_CIPHER_LIST

Frenzy answered 5/6, 2015 at 11:20 Comment(1)
What cipher do I give it? ecdhe_ecdsa_aes_128_sha? Won't that break other sites that are using different ciphers?Frye
E
2

You just need to add to your curl options in PHP

curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'DEFAULT:!DH');

on on the shell

curl -I --ciphers 'DEFAULT:!DH' https://sslspdy.com
Eudy answered 16/10, 2020 at 11:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.