C#和dotnet 4.7.1没有为TLS 1.2调用添加自定义证书

我有以下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为used,是支持的密码之一。

在wireshark中,我可以看到,通过工作调用(C#/ Tls 1.1和Curl Tls 1.2),证书将被发送到服务器。 这是C#tls 1.1调用的wireshark转储:

Wireshark转储 -  Csharp转1.1

但是,在wireshark中,我可以看到,使用C#/ Tls 1.2,没有证书从客户端发送到服务器。 这是C#tls 1.2调用的wireshark转储:

在此处输入图像描述

谁能看到我在这里失踪的东西?

UPDATE

似乎证书有一个md5签名,Windows中的Schannel不支持tls 1.2。 我们的供应商为我们创建了另一个证书作为解决方案。

我遇到了这个讨论问题的随机线程: https : //community.qualys.com/thread/15498

您找对此问题的根本原因是:默认情况下,基于schannel的客户端提供SHA1,SHA256,SHA384和SHA512(在Win10 / Server 2016上)。 因此,TLS 1.2服务器不应将其MD5证书发送给这些客户端。

客户端(HttpClient)未在signature_algorithms扩展中列出MD5,因此TLS 1.2握手失败。 修复是使用安全服务器证书。

我相信这段代码总是盲目地返回true来屏蔽某种类型的证书错误:

 handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => true; 

我建议你有一个function来真正分析arg4的结果。 这是您的SSL策略错误。 记录它们,你会得到你的答案。 在我的示例中,我写入控制台,但您可以写入跟踪或文件。 您将获得一个与SslPolicyErrors枚举值相关联的数字。 根据结果​​,您可能需要检查arg3,这是您的链。

 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => { SslPolicyErrors errs = sslPolicyErrors; Console.WriteLine("Policy Errors " + sslPolicyErrors.ToString()); return true;}; 

你不应该指定处理程序的SslProtocols属性吗?

hander定义后尝试添加此行:

 handler.SslProtocols = SslProtocols.Tls12;