如何在php中添加密码来卷曲?

时间:2015-06-05 11:14:43

标签: php ssl curl openssl nss

我正在尝试使用php curl连接到一个站点,但是得到错误“没有常见的加密算法”。进一步调查,我认为这与NSS有关?我发现从命令行,我可以重现错误(所以问题肯定是curl而不是php包装器),但是如果我设置--ciphers ecdhe_ecdsa_aes_128_sha然后它可以工作:

[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

所以我的问题是,

  1. 为什么会这样?我无法在网上找到关于ssl密码如何在curl中工作的解释;似乎每个页面的编写都假设读者已经是该领域的专家 - 不幸的是,像“你可能正在使用NSS,所以尝试切换PKCS for FIPS”的句子对我来说是完全不可理解的,并且谷歌搜索只会解释各个组成部分(通常参考20年前的标准),而不是它们彼此之间的关系。

  2. 有什么方法可以让curl告诉我它正在尝试哪些密码以及服务器会接受哪些密码?我试过在ssllabs上查找服务器,但似乎是说服务器接受所有密码,显然它没有。

  3. 我需要将哪些选项传递给curl_setopt,以便我的php脚本能够连接到此服务器?

  4. 如果我将密码设置为此,是否会破坏其他网站?有什么我可以这样做,以便curl能够连接到所有安全站点,或者我是否必须手动迭代不同的密码尝试每个密码以找出哪个有效?

4 个答案:

答案 0 :(得分:4)

  
      
  1. 为什么会这样?我无法在网上找到关于ssl密码如何在curl中工作的解释
  2.   

这取决于一些事情。客户端和服务器库,客户端和服务器配置等。您需要提供更多详细信息。

  
      
  1. 有什么方法可以让卷曲告诉我哪些密码
  2.   

使用正确的工具完成工作。在这种情况下,它更新了sslscan

  
      
  1. 我需要将哪些选项传递给curl_setopt,以便我的php脚本能够连接到此服务器?
  2.   

CURLOPT_SSL_CIPHER_LIST

  
      
  1. 如果我将密码设置为此,是否会破坏其他网站?
  2.   

也许。这取决于特定网站的配置。

理想情况下,您选择12或16个您认可的密码套件,然后使用它们而不是一个。 12或16涵盖了您在互联网上遇到的大多数网站。

这是我经常使用的列表。来自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

我想放弃TLS_RSA_*密码套件,因为它们是密钥传输,但我需要它们用于我遇到的旧IIS服务器。

从下面的扫描结果中可以看出,此列表与服务器列表相交。

请注意,您没有指定,例如TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384。相反,在OpenSSL中,您为套件指定OpenSSL的名称ECDHE-ECDSA-AES256-SHA384。您可以在documentation for openssl ciphers找到OpenSSL名称。

使用OpenSSL,您还可以使用字符串"HIGH:!aNULL:!MD5:!RC4:!PSK:!SRP"。这将使你获得大约40或50个相当不错的选择。

您可以运行OpenSSL密码命令来查看列表是什么:

$ 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
...

您可以使用sslscan的更新版本来确定可用的密码套件:

$ 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

答案 1 :(得分:3)

  

我无法在网上找到关于ssl密码如何在curl中工作的解释; ...

这不是特定于卷曲。使用SSL / TLS,客户端提供它愿意使用的密码,服务器也从这些密码中选择它所支持的密码。默认情况下,客户不会提供所有密码,特别是不会被认为是弱密码的密码。

  

有什么方法可以让curl告诉我它正在尝试哪些密码以及服务器会接受哪些密码?

使用wireshark,您可以看到客户端提供了哪些密码。您也可以检查您的客户 https://www.ssllabs.com/ssltest/viewMyClient.html显示提供了哪些密码。或者使用openssl s_server -cipher ALL -www创建一个测试服务器并将客户端连接到它,它将显示客户端和服务器共享的密码。

  

我需要将哪些选项传递给curl_setopt ...

CURLOPT_SSL_CIPHER_LIST

ECDHE-ECDSA-AES128-SHA可能适用于您的情况。但是这个值实际上取决于你的卷曲是如何编译的。 Curl支持不同的SSL / TLS后端,如OpenSSL,NSS,SecureTransport,SChannel,GnuTLS,确切的语法取决于后端。此示例设置对OpenSSL后端有效。

  

如果我将密码设置为此,是否会破坏其他网站? ...

如果你将自己限制在全局范围内,那么是。对于全局设置,您最好也添加其他设置,即HIGH:ECDHE-ECDSA-AES128-SHA:!aNULL。再次出错,确切的语法取决于SSL / TLS后端。

答案 2 :(得分:2)

curl_setoptDouble[] asArray = list.toArray(new Double[list.size()]);

一起使用

答案 3 :(得分:1)

您只需要在PHP中添加curl选项即可

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

在外壳上

curl -I --ciphers 'DEFAULT:!DH' https://sslspdy.com