我已经用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,但远程服务器上没有启用:
事实上,我对SSPI知之甚少,大部分只是维基百科上的摘要:
安全支持提供程序接口(SSPI)是Win32 API,供以下人员使用 Microsoft Windows系统执行各种与安全性相关的操作 验证之类的操作。
所以,这似乎是问题的原因-但是...
我成功地将SslProtocols
的类型从SslProtocols.Tls12
更改为SslProtocols.Tls
,从而实现了成功的沟通。但是,据我所知,SSPI并不与任何特定的SSL协议绑定,那么为什么这样做有效?
这是暂时的解决方法,但是我真的很想了解导致此问题的潜在问题。任何人都可以对这里发生的事情有所了解吗?
我宁愿完全支持TLS 1.2,而不必降级。
答案 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。
但是,相反,让他们自动协商有一些缺点:
SSLv23_METHOD
(例如,您也有TLSv1_2_METHOD
),而不是表示SSL 2或SSL 3(现在应该消失的两件事),但“无论如何我们都可以自动协商”(关于在Web外部正确设计和使用TLS API的通用问题,这是令人大开眼界的论文:{ {3}})