. NET сброс сертификата клиента через TLS 1.2 - PullRequest
1 голос
/ 16 января 2020

Здравствуйте, кажется, что какую-то форму этого вопроса задавали миллион различных способов, но многие не имеют ответов, или ответы не относятся ко мне.

У нас есть тривиальный маленький номер. NET сервис, который вызывает сторонний API, который теперь поддерживает только TLS 1.2.

        var requestHandler = new WebRequestHandler();
        var clientCert = GetClientCert("THUMBPRINT");

        requestHandler.ClientCertificates.Add(clientCert);
        var encodedHeader = "FOO";
        var httpClient = new HttpClient(requestHandler) { BaseAddress = new Uri("https://foo.bar.com/rest/api/") };
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", encodedHeader);

        var httpResponse = httpClient.GetAsync("").Result;
        var responseContent = httpResponse.Content.ReadAsStringAsync().Result;

Когда я явно устанавливаю протокол безопасности на 1.2 или нацеливаю фреймворк, который по умолчанию равен 1.2, сертификат клиента не является частью пакета, который идет на сервер. Я проверил это в Wireshark, и сертификаты никогда не присутствуют выше 1.2. В этот момент сервер отправляет сообщение Fatal Alert Handshake Failure (40), которое приводит к следующему исключению: Net:

The request was aborted: Could not create SSL/TLS secure channel.

Я могу сделать такой же вызов через Chrome или Почтальон (собственный) и это работает отлично. Если я установлю протокол до 1.1, он будет работать нормально. Но если я запускаю его как 1.2 через NET, он каждый раз терпит неудачу. Я получаю точно такую ​​же ошибку и тот же трафик c в Wireshark, даже если я намеренно не добавляю свой сертификат клиента вообще.

Я пропустил стороннюю конечную точку через https://www.ssllabs.com/ и это хорошо. Там нигде нет подписей MD5, которые я могу видеть с обеих сторон. Все подписано sha1 или sha256 с шифрованием RSA.

У меня включена трассировка. Следующий вывод указывает на то, что нет проблем с поиском сертификата или его закрытого ключа:

System.Net Information: 0 : [19512] SecureChannel#41622463 - Certificate is of type X509Certificate2 and contains the private key.
System.Net Information: 0 : [19512] SecureChannel#41622463::.AcquireClientCredentials, new SecureCredential() (flags=(ValidateManual, NoDefaultCred, SendAuxRecord, UseStrongCrypto), m_ProtocolFlags=(Zero), m_EncryptionPolicy=RequireEncryption)
System.Net Information: 0 : [19512] AcquireCredentialsHandle(package = Microsoft Unified Security Protocol Provider, intent  = Outbound, scc     = System.Net.SecureCredential)
System.Net Information: 0 : [19512] InitializeSecurityContext(credential = 
System.Net.SafeFreeCredential_SECURITY, context = 1ed7465db80:1f1d854c910, targetName = foo.bar.com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation)
System.Net Information: 0 : [19512] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=133, returned code=ContinueNeeded).

У меня также включена регистрация событий SCHANNEL. Там я вижу, как он получает сертификат клиента с закрытым ключом.

The TLS client credential's private key has the following properties:

   CSP name: Microsoft Enhanced Cryptographic Provider v1.0
   CSP type: 1
   Key name: {some hex here}
   Key Type: key exchange
   Key Flags: 0x0

 The attached data contains the certificate.

За ним следует ошибка, соответствующая пакету оповещений в Wireshark:

A fatal alert was received from the remote endpoint. The TLS protocol defined fatal alert code is 40.

Я полностью отсутствует идей. Это похоже на ошибку в. Net. На мгновение мы подумали, что это неполная цепочка доверия с нашим клиентским сертификатом, потому что в нашем пакете сертификатов был только клиентский сертификат и промежуточный ЦС. Но мы получили Root CA от поставщика, и теперь Windows говорит, что сертификат является le git.

Одна интересная вещь, которую я заметил в Wireshark, это то, что мы отправляем клиентский сертификат И промежуточный CA на Успешные звонки. Я не знаю, как он поднимает промежуточный ЦС, потому что я только получаю сертификат клиента, чтобы присоединить его к запросу. Почему он не отправит root CA, как только он у нас будет? Моя интуиция говорит мне, что проблема все еще может быть где-то здесь, но я не могу доказать это. В любом журнале нигде нет ничего, что указывало бы на сбой в цепи доверия.

Я даже подключил ProcMon, чтобы посмотреть, вижу ли я что-то не так, но ничего не выпрыгнуло. Чувак, я мог бы переписать все это в Java за количество времени, которое я потратил на это.

Некоторые другие вещи, которые я пробовал, не сработали:

таргетинг. Net 4.8

машинное хранилище против пользовательского хранилища

загрузка непосредственно из pfx вместо

HttpWebRequest вместо HttpClient

TcpClient с SslStream

новее Windows 10 выпуск

EDIT Я только что прочитал что-то, что говорит, что подписи SHA-1 были также удалены из TLS 1.2 вместе с MD5. Сертификат нашего клиента подписан в SHA-1. Я думаю, что это может быть, и мы связываемся с нашим продавцом.

1 Ответ

0 голосов
/ 17 января 2020

Моя проблема и мое решение в итоге оказались такими же, как эта. Разница лишь в том, что мой клиентский сертификат был SHA1, а не MD5. . NET также явно отбрасывает сертификаты SHA1.

C# и tnet 4.7.1 не добавляет пользовательский сертификат для вызовов TLS 1.2

Это статья дала мне подсказку, потому что другие посты указывали, что SHA1 все еще принимается Мои сертификаты SHA1 все еще работали за пределами. NET.

https://tools.ietf.org/id/draft-ietf-tls-md5-sha1-deprecate-00.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...