Здравствуйте, кажется, что какую-то форму этого вопроса задавали миллион различных способов, но многие не имеют ответов, или ответы не относятся ко мне.
У нас есть тривиальный маленький номер. 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. Я думаю, что это может быть, и мы связываемся с нашим продавцом.