CentOS PHP curl无法协商一组可接受的安全参数

时间:2015-11-01 17:19:42

标签: php curl openssl nss

在Ubuntu 14.04.3上,这段代码工作正常:

$url_login = "https://test.example.com/login.do";

$cert_file = '/var/www/html/test/cert.pem';
$ssl_key = '/var/www/html/test/cert_private.pem';

$post_fields = 'userAction=1&cancelReason=&cancelType=&account=&memoType=&userText=&userid=99999999&password=xxxxxxxxxxxxxxxx';

$ch = curl_init();

$options = array( 
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_HEADER         => 1,
    CURLOPT_FOLLOWLOCATION => 1,
    CURLOPT_SSL_VERIFYHOST => 0,
    CURLOPT_SSL_VERIFYPEER => 0,

    CURLOPT_USERAGENT => 'Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)',
    CURLOPT_VERBOSE        => 0,
    CURLOPT_URL => $url_login ,

    CURLOPT_SSLCERT => $cert_file ,
    CURLOPT_SSLCERTTYPE, 'PEM',
    CURLOPT_SSLKEY => $ssl_key,

    CURLOPT_COOKIESESSION => 1,

    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $post_fields
);

curl_setopt_array($ch , $options);

$output = curl_exec($ch);

Ubuntu上的php正在使用curl和openssl。

在Centos 7上如果失败,请执行以下操作:

Curl Error : SSL peer was unable to negotiate an acceptable set of security parameters.

curl在这里用nss。

“cert.pem”仅包含带有证书链的客户端证书,“cert_private.pem”包含不受密码保护的私钥。 (-----开始RSA私钥-----)。

如何让上述PHP代码兼容? curl的openssl和nss实现?

2 个答案:

答案 0 :(得分:0)

如何纠正:

CURLOPT_SSLCERTTYPE, 'PEM',

CURLOPT_SSLCERTTYPE => 'PEM',

答案 1 :(得分:0)

我也使用nss进行客户端证书身份验证时遇到此问题,而openssl工作正常。

经过大量测试,这就是我与我们尝试联系的服务器建立的关系:

  • 使用TLS v1.2卷曲(在某些情况下默认为客户端证书失败)
  • 使用TLS v1.2卷曲,服务器需要客户端证书,但客户端未使用,连接成功。但是,客户端未经过身份验证。
  • 使用TLS v1.0卷曲并且客户端证书成功

无论密码套件如何,上述情况都会发生,通常我们会使用rsa_aes_256_cbc_sha_256。

快速解决方法是强制使用TLS v1.0:

CURLOPT_SSLVERSION => 4,

显然,这不是理想的,您的服务器可能不支持它。

另一种选择是使用openssl甚至GnuTLS编译curl(虽然我没有测试后者)而不是nss。同样,这可能不是一种选择。

到目前为止,这指出了NSS的一个问题。如果进一步调试产生任何有用的信息,我将更新此答案。

仅供参考,这是在命令行上使用curl的完整错误消息:

* NSS error -12227 (SSL_ERROR_HANDSHAKE_FAILURE_ALERT)
* SSL peer was unable to negotiate an acceptable set of security parameters.
* Closing connection 0
curl: (35) SSL peer was unable to negotiate an acceptable set of security parameters.

更新2015-11-24:使用Wireshark和ssltap进行的进一步测试显示初始握手成功,连接到客户端发送ChangeCipherSpec,然后加密"完成& #34;消息。

然后,服务器应解密客户端"已完成"消息,验证哈希和MAC并用自己的加密响应"完成"信息。相反,服务器正在响应" handshake_failure"在这一点上。

这应该提供NSS失败的地方的线索。

Chrome,Openssl和Charles Proxy都可以使用客户端证书进行身份验证。 Firefox(使用NSS)和curl(使用NSS)都失败了。

更新2015-11-27:服务器运营团队提供的其他信息表明,这可能是不合规服务器的问题。只有在某些情况下使用TLS 1.2时才会出现此问题。这可以解释为什么一些SSL库(如OpenSSL)足够灵活,可以解决它。

NSS在遵守RFC方面可能更为严格。如果/当我们从管理服务器的运营团队听到更多信息时,我会更新答案。

更新2017-01-25:网络服务器软件和负载均衡器是为特定银行的支付网关定制的。我们最近再次尝试使用新客户端,现在服务器似乎可以与使用NSS或OpenSSL构建的Curl一起使用,并且不再看到错误。总结:解决方法是使用不同的SSL库并等待开发人员修复服务器软件。