简体   繁体   English

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

[英]C# and dotnet 4.7.1 not adding custom certificate for TLS 1.2 calls

I have the following C# code, constructing an https call with a custom certificate. 我有以下C#代码,使用自定义证书构建https调用。 When using Tls 1.1, the call works fine. 使用Tls 1.1时,通话正常。 When using Tls 1.2 the call breaks. 使用Tls 1.2时,呼叫会中断。 I using curl, using tls 1.2 works fine as well. 我使用curl,使用tls 1.2也可以正常工作。

C# Code: 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;

Works with: 适用于:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;

Error with: 错误:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

.Net error message: SocketException: An existing connection was forcibly closed by the remote host .Net错误消息: SocketException:远程主机强制关闭现有连接

.Net version : 4.7.1 .Net版本:4.7.1

OS: Windows 10 version 1703 (supported cipher list: https://msdn.microsoft.com/en-us/library/windows/desktop/mt808163(v=vs.85).aspx ) - and the server specifies TLS_RSA_WITH_AES_256_GCM_SHA384 to be used, which is among the supported ciphers. 操作系统: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,是支持的密码之一。

In wireshark I can see that with the working calls (C#/Tls 1.1 and Curl Tls 1.2) the certificate is being sent to the server. 在wireshark中,我可以看到,通过工作调用(C#/ Tls 1.1和Curl Tls 1.2),证书将被发送到服务器。 Here is the wireshark dump for the C# tls 1.1 call: 这是C#tls 1.1调用的wireshark转储:

Wireshark转储 -  Csharp转1.1

However, also in wireshark, I can see that with C#/Tls 1.2 there is no certificate being sent from the client to the server. 但是,在wireshark中,我可以看到,使用C#/ Tls 1.2,没有证书从客户端发送到服务器。 Here is the wireshark dump for the C# tls 1.2 call: 这是C#tls 1.2调用的wireshark转储:

在此输入图像描述

Can anyone see what I am missing here? 谁能看到我在这里失踪的东西?

UPDATE UPDATE

It seems the certificate has an md5 signature which is not supported by Schannel in windows in combination with tls 1.2. 似乎证书有一个md5签名,Windows中的Schannel不支持tls 1.2。 Our vendor has created another certificate to us as a solution. 我们的供应商为我们创建了另一个证书作为解决方案。

I came across this random thread that discusses the issue: https://community.qualys.com/thread/15498 我遇到了这个讨论问题的随机线程: https//community.qualys.com/thread/15498

You are right on the root cause of this problem: By default, schannel-based clients offer SHA1, SHA256, SHA384 and SHA512 (on Win10/Server 2016). 您找对此问题的根本原因是:默认情况下,基于schannel的客户端提供SHA1,SHA256,SHA384和SHA512(在Win10 / Server 2016上)。 So TLS 1.2 servers are not supposed to send their MD5 certs to these clients. 因此,TLS 1.2服务器不应将其MD5证书发送给这些客户端。

The client (HttpClient) does not list MD5 in the signature_algorithms extension, so the TLS 1.2 handshake fails. 客户端(HttpClient)未在signature_algorithms扩展中列出MD5,因此TLS 1.2握手失败。 The fix is to use a secure server cert. 修复方法是使用安全服务器证书。

I believe this code is masking some type of certificate error by always blindly returning true: 我相信这段代码总是盲目地返回true来屏蔽某种类型的证书错误:

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

I recommend you have a function to truly analyze the results of arg4. 我建议你有一个真正分析arg4结果的功能。 That is your SSL policy errors. 这是您的SSL策略错误。 Log them and you will get your answer. 记录它们,你会得到你的答案。 In my example, I write to the console, but you can write to the trace, or a file. 在我的示例中,我写入控制台,但您可以写入跟踪或文件。 You'll get a number which will be associated a value for the SslPolicyErrors enumeration. 您将获得一个与SslPolicyErrors枚举值相关联的数字。 Based on the results you might need to check your arg3, which is your chain. 根据结果​​,您可能需要检查arg3,这是您的链。

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => {

SslPolicyErrors errs = sslPolicyErrors;
Console.WriteLine("Policy Errors " + sslPolicyErrors.ToString());           
return true;};

Shouldn't you specified the handler's SslProtocols property? 你不应该指定处理程序的SslProtocols属性吗?

Try adding this line after hander definition: hander定义后尝试添加此行:

handler.SslProtocols = SslProtocols.Tls12;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM