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,
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.
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.
What options do I need to pass to curl_setopt so that my php script is able to connect to this server?
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?
- 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.
- 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
.
- 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
.
- 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?:
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