使用cURL(PHP)和C#REST API和SslStream类使用SSL / TLS错误

时间:2018-08-22 23:01:06

标签: c# php ssl curl

我已经用C#编写了REST API服务器,它使用System.Net.Security.SslStream类提供SSL / TLS加密。

我还在创建一个Web服务,该服务使用PHP + cURL处理与服务器的通信。

在本地,我将WAMP用作测试环境,并且一切正常。

但是,在远程环境上进行上传和测试时,通信失败并显示以下错误消息:

cURL错误

Unknown SSL protocol error in connection to mywebsite.example:443

SslStream错误

AuthenticationException in SslStream.AuthenticateAsServer()

A call to SSPI failed, see inner exception.

Inner exception: The client and server cannot communicate, because they do not possess a common algorithm

尝试使用TLS 1.2身份验证时会发生此异常和错误:

SslStream.AuthenticateAsServer(ServerCertificate, false, SslProtocols.Tls12, true);

我尝试设置各种cURL选项,例如:

    curl_setopt($curl, CURLOPT_SSLVERSION,CURL_SSLVERSION_TLSv1_2);

但是,a,没有欢乐。

在检查phpInfo()配置中是否存在差异之后,我注意到本地cURL设置中启用了SSPI,但远程服务器上没有启用:

cURL settings

事实上,我对SSPI知之甚少,大部分只是维基百科上的摘要:

  

安全支持提供程序接口(SSPI)是Win32 API,供以下人员使用   Microsoft Windows系统执行各种与安全性相关的操作   验证之类的操作。

所以,这似乎是问题的原因-但是...

我成功地将SslProtocols的类型从SslProtocols.Tls12更改为SslProtocols.Tls,从而实现了成功的沟通。但是,据我所知,SSPI并不与任何特定的SSL协议绑定,那么为什么这样做有效?

这是暂时的解决方法,但是我真的很想了解导致此问题的潜在问题。任何人都可以对这里发生的事情有所了解吗?

我宁愿完全支持TLS 1.2,而不必降级。

1 个答案:

答案 0 :(得分:1)

问题实际上与SSPI无关。

SslProtocols.Tls可能意味着:“自动协商任何合适的通用版本”,而SslProtocols.Tls12则意味着:“强制TLS版本1.2”

因此,如果您强制使用TLS 1.2,但并非所有各方都知道此版本,则握手将失败。 通过让他们自动协商,他们可能可以融合到TLS 1.1或1.0

请注意,如今,除TLS 1.2之外的任何其他东西都不是一个好主意,或者至少它确实应该是一个临时情况。 TLS 1.3也在2周前作为标准发布了。

通常最好让系统自动协商版本,以使它们在升级时可以降到当时最高的版本。因此,即使短期内强制使用SslProtocols.Tls12也是有效的(目前是最佳TLS版本),但长期而言则不是(如果您的两个系统都已升级并且在将来能够使用TLS 1.3,则强制)不会从中获利,可悲的是1.3在许多方面都优于1.2。

但是,相反,让他们自动协商有一些缺点:

  1. 虽然主要用于修饰,但在OpenSSL中具有这种自动协商功能的符号常量被误导称为SSLv23_METHOD(例如,您也有TLSv1_2_METHOD),而不是表示SSL 2或SSL 3(现在应该消失的两件事),但“无论如何我们都可以自动协商”(关于在Web外部正确设计和使用TLS API的通用问题,这是令人大开眼界的论文:{ {3}})
  2. 更重要的是,如果您不注意正在发生的事情(记录),则当您同时希望有更好的功能时,系统可能会自动协商非常低的版本,例如TLS 1.0甚至更差的SSL 3.0。因此,您可能具有正在运行的系统,但未达到所需的安全级别。