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

China☆狼群 提交于 2020-01-02 00:51:14

问题


I have the following C# code, constructing an https call with a custom certificate. When using Tls 1.1, the call works fine. When using Tls 1.2 the call breaks. I using curl, using tls 1.2 works fine as well.

C# Code:

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 version : 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.

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. Here is the wireshark dump for the C# tls 1.1 call:

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. Here is the wireshark dump for the C# tls 1.2 call:

Can anyone see what I am missing here?

UPDATE

It seems the certificate has an md5 signature which is not supported by Schannel in windows in combination with 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


回答1:


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). So TLS 1.2 servers are not supposed to send their MD5 certs to these clients.

The client (HttpClient) does not list MD5 in the signature_algorithms extension, so the TLS 1.2 handshake fails. The fix is to use a secure server cert.




回答2:


I believe this code is masking some type of certificate error by always blindly returning true:

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

I recommend you have a function to truly analyze the results of arg4. That is your SSL policy errors. 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. Based on the results you might need to check your arg3, which is your chain.

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

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



回答3:


Shouldn't you specified the handler's SslProtocols property?

Try adding this line after hander definition:

handler.SslProtocols = SslProtocols.Tls12;


来源:https://stackoverflow.com/questions/47904777/c-sharp-and-dotnet-4-7-1-not-adding-custom-certificate-for-tls-1-2-calls

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!