我有以下C#代码,使用自定义证书构建https调用。使用Tls 1.1时,通话正常。使用Tls 1.2时,呼叫会中断。我使用curl,使用tls 1.2也可以正常工作。
C#代码:
X509Certificate2Collection collection = new X509Certificate2Collection();
collection.Import("C:\\SomePath\\MyCertificate.pfx", "MyPassword", X509KeyStorageFlags.PersistKeySet);
var cert = collection[0];
ServicePointManager.SecurityProtocol = ...;
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => true;
HttpClientHandler handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true;
handler.ClientCertificates.Add(cert);
var content = new ByteArrayContent(Encoding.GetEncoding("latin1").GetBytes("Hello world"));
HttpClient client = new HttpClient(handler);
var resp = client.PostAsync(requestUri: url, content: content).Result.Content.ReadAsStringAsync().Result;
适用于:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;
错误:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
.Net错误消息: SocketException:远程主机强行关闭现有连接
.Net版本:4.7.1
操作系统:Windows 10版本1703(支持的密码列表:https://msdn.microsoft.com/en-us/library/windows/desktop/mt808163(v=vs.85).aspx) - 服务器指定要使用的TLS_RSA_WITH_AES_256_GCM_SHA384,这是受支持的密码之一。
在wireshark中,我可以看到,通过工作调用(C#/ Tls 1.1和Curl Tls 1.2),证书将被发送到服务器。这是C#tls 1.1调用的wireshark转储:
然而,在wireshark中,我可以看到,使用C#/ Tls 1.2,没有证书从客户端发送到服务器。这是C#tls 1.2调用的wireshark转储:
谁能看到我在这里缺少的东西?
更新
证书似乎有一个md5签名,Windows中的Schannel不支持tls 1.2。我们的供应商已经为我们创建了另一个证书作为解决方案。
我遇到了这个讨论问题的随机主题:https://community.qualys.com/thread/15498
答案 0 :(得分:2)
您正确解决此问题的根本原因:默认情况下,基于schannel的客户端提供SHA1,SHA256,SHA384和SHA512(在Win10 / Server 2016上)。因此,TLS 1.2服务器不应将其MD5证书发送给这些客户端。
客户端(HttpClient)未在signature_algorithms扩展中列出MD5,因此TLS 1.2握手失败。修复方法是使用安全服务器证书。
答案 1 :(得分:0)
我相信这段代码总是盲目地返回true来屏蔽某种类型的证书错误:
handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true;
我建议你有一个真正分析arg4结果的功能。这是您的SSL策略错误。记录它们,你会得到你的答案。在我的示例中,我写入控制台,但您可以写入跟踪或文件。您将获得一个与SslPolicyErrors枚举值相关联的数字。根据结果,您可能需要检查arg3,这是您的链。
ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => {
SslPolicyErrors errs = sslPolicyErrors;
Console.WriteLine("Policy Errors " + sslPolicyErrors.ToString());
return true;};
答案 2 :(得分:0)
您是否应该指定处理程序的SslProtocols
属性?
尝试在hander
定义后添加此行:
handler.SslProtocols = SslProtocols.Tls12;