【问题标题】:How to add ciphers to curl in php?如何在 php 中为 curl 添加密码?
【发布时间】:2015-08-20 07:42:56
【问题描述】:

我正在尝试使用 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 切换为 FIPS”这样的句子对我来说是完全无法理解的,并且谷歌搜索只会解释各个组成部分(通常参考 20 年前的标准),而不是它们之间的关系。

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

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

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

【问题讨论】:

    标签: php ssl curl openssl nss


    【解决方案1】:

    curl_setoptCURLOPT_SSL_CIPHER_LIST 一起使用

    【讨论】:

    • 我给它什么密码? ecdhe_ecdsa_aes_128_sha?这不会破坏使用不同密码的其他网站吗?
    【解决方案2】:

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

    这不是特定于 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 是如何编译的。 Curl 支持不同的 SSL/TLS 后端,如 OpenSSL、NSS、SecureTransport、SChannel、GnuTLS,具体语法取决于后端。此示例设置对 OpenSSL 后端有效。

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

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

    【讨论】:

      【解决方案3】:
      1. 为什么会这样?我无法在网上找到关于 ssl 密码如何在 curl 中工作的解释

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


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

      为工作使用正确的工具。在这种情况下,它是一个更新的sslscan


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

      CURLOPT_SSL_CIPHER_LIST.


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

      也许吧。这取决于该特定站点的配置。

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

      这是我通常使用的列表。来自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 ciphers 命令来查看列表是什么:

      $ 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
      

      【讨论】:

      • 这对于展示 server 支持的密码非常有用。但是我们需要知道 curl 支持什么密码。并且 curl 在 --ciphers 中使用的名称是不同的。例如,一个特定的路由器需要 openssl 调用的 TLS_RSA_WITH_AES_256_CBC_SHA——但这不适用于 curl。
      【解决方案4】:

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

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

      在外壳上

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

      【讨论】:

        猜你喜欢
        • 2018-07-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-17
        • 2013-02-24
        • 1970-01-01
        相关资源
        最近更新 更多