С# и dotnet 4.7.1 не добавление специального сертификата для вызовов TLS 1.2
У меня есть следующий код С#, создающий вызов https с помощью специального сертификата. При использовании Tls 1.1 вызов работает нормально. При использовании Tls 1.2 вызов прерывается. Я использую curl, используя tls 1.2, отлично работает.
Код С#:
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;
. Сообщение об ошибке: 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, который будет использоваться, что среди поддерживаемых шифров.
В wirehark я вижу, что с рабочими вызовами (С#/Tls 1.1 и Curl Tls 1.2) сертификат отправляется на сервер. Вот дамп проводов для вызова С# tls 1.1:
![Дамп Wireshark - Csharp tls 1.1]()
Однако, также в wirehark, я вижу, что с С#/Tls 1.2 от клиента к серверу не отправляется сертификат. Вот дамп проводов для вызова С# tls 1.2:
![введите описание изображения здесь]()
Может ли кто-нибудь увидеть, чего я здесь не вижу?
UPDATE
Кажется, что у сертификата есть подпись md5, которая не поддерживается Schannel в окнах в сочетании с tls 1.2. Наш поставщик создал для нас еще один сертификат как решение.
Я столкнулся с этой случайной нитью, которая обсуждает проблему: https://community.qualys.com/thread/15498
Ответы
Ответ 1
Я считаю, что этот код маскирует некоторый тип ошибки сертификата, всегда слепо возвращая 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
Не следует ли указать свойство handler SslProtocols
?
Попробуйте добавить эту строку после определения hander
:
handler.SslProtocols = SslProtocols.Tls12;