Приложение .NET не может отправить сертификат клиента — Win 7 или Win XP?

Я разрабатываю веб-приложение ASP.NET, которое отправляет запрос на другой сервер с помощью HttpWebRequest. Он отправляет запрос по HTTPS, а удаленному серверу требуется сертификат клиента. Запрос не выполняется в приложении .NET, по-видимому, не удается отправить правильный сертификат клиента. Я могууспешно подключиться и отправить клиентский сертификат, если просто зайду по URL-адресу в веб-браузере (в частности, в Chrome).

Приведенный ниже код представляет собой простое воспроизведение с простым запросом GET.

var r = WebRequest.Create(url) as HttpWebRequest;
r.ClientCertificates = new X509CertificateCollection { myX509Cert };
using (var resp = r.GetResponse() as HttpWebResponse) {
    ...
}

Я получаю наше любимое исключение: «Не удалось создать защищенный канал SSL/TLS». Как правило, эти типы проблем указывают на проблемы с разрешениями на закрытый ключ вашего сертификата. Я перепробовал все, что мог придумать, чтобы убедиться, что все настроено правильно, но, возможно, я что-то упустил. Короче говоря, удаленный сервер отправляет TLS CertificateRequestсо списком, который, кажется, правильно идентифицирует мой клиентский сертификат, но мое приложение не отвечает ни одним клиентским сертификатом.

Вот мои настройки:

  • Windows 7 Professional, 64-разрядная версия
  • Возможность воспроизвести проблему в приложении ASP.NET MVC 3/.NET 4, работающем на сервере разработки Visual Studio, ASP.NET WebForms/. NET 3.5, работающее в локальном IIS, и в консольном приложении .NET/.NET 4
  • Microsoft .NET Framework 4.5 был недавно установлен. Еще не проверял, может ли это быть проблемой.

Вот все, что я пробовал и что мне известно:

  • Этот код работал нормально при работе на компьютере с Windows XP
  • сертификат клиента импортирован в локальный компьютер, хранилище личных сертификатов с правильно настроенными разрешениями для закрытого ключа для меня и всех соответствующих пользователей IIS
  • Я несколько раз пытался переустановить сертификат на своем компьютере
  • Я подтвердил, что Приложение .NET может получить доступ к сертификату X509, и HasPrivateKey = true
  • Гарантировано, что сертификат моего клиента действителен. На самом деле это сертификат SSL для веб-сервера, на котором будет работать это приложение.
  • Я установил PreAuthenticate = trueв объекте запроса. Не имеет значения
  • Я попытался установитьServicePointManager.Expect100Continue = false, не имеет значения
  • Я попытался установить ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3, но, видимо, удаленному серверу требуется TLS, так что это не помогает.
  • Я установил делегат ServicePointManager.ServerCertificateValidationCallbackтак, чтобы он всегда возвращал true. Но запрос терпит неудачу ранее в рукопожатии TLS, прежде чем он даже дойдет до точки вызова этого делегата
  • Когда я перехожу к URL-адресу в Chrome, он просит меня предоставить сертификат клиента, представляет правильный сертификат клиента как выбор , я выбираю этот сертификат и получаю действительный ответ. Также работает правильно, когда я создаю запрос в Fiddler.Таким образом, определенно проблема связана именно с моим кодом .NET, а не с самим сертификатом или удаленным сервером и т. д.
  • У поставщика, с которым я работаю, такая же служба настроена на другом удаленном сервере, и это для службы требуется другой сертификат клиента. Итак, я попробовал то же самое с другим URL-адресом и сертификатом клиента и получил ту же ошибку

. Я добавил трассировку System.Net и увидел это:

SecureChannel # 26717201 - у нас есть предоставленные пользователем сертификаты. . Сервер указал 6 эмитентов. Ищем сертификаты, которые соответствуют любому из эмитентов.

SecureChannel#26717201 — осталось 0 клиентских сертификатов на выбор.

...

InitializeSecurityContext (количество входных буферов = 2, длина исходящего буфера = 0, возвращенный код = CertUnknown).

Я включил полное ведение журнала SCHANNELи увидел это предупреждение:

Удаленный сервер запросил аутентификацию клиента SSL, но не удалось найти подходящий сертификат клиента. Будет предпринята попытка анонимного подключения. Этот запрос на соединение SSL может быть успешным или неудачным, в зависимости от настроек политики сервера.

Я запустил Wireshark и увидел, что удаленный сервер отправил CertificateRequest, и, похоже, у него есть запись Distinguished Nameс указанными значениями CN\OU\O моего клиентского сертификата. точно. После этого мое приложение отправляет ответ сертификата без сертификатов.

Похоже, я что-то упустил при настройке этого сертификата для правильной работы с приложениями .NET в Windows 7.Мое лучшее предположение состоит в том, что на моем новом компьютере с Windows 7 есть что-то другое, по сравнению с компьютером с XP, что приводит к сбою сейчас. В настоящий момент у меня нет доступа к среде Windows XP, чтобы подтвердить это;Я буду через пару дней, но действительно хотел бы решить эту проблему как можно скорее.

Будем признательны за любые идеи. Спасибо!

РЕДАКТИРОВАТЬКак описано выше, при подключении к URL-адресу в Chrome браузер запрашивает у меня сертификат клиента, и я могу предоставить правильный сертификат и успешно подключиться. Однако я не могу сделать это успешно в Internet Explorer (9). Я просто получаю «Internet Explorer не может отобразить веб-страницу» без каких-либо других подсказок или объяснений. Мне сказали, что это может иметь значение, поскольку WebRequest.Createведет себя аналогично IE. Я изучаю, что это может означать, но ценю любые мысли по этому поводу.

РЕДАКТИРОВАТЬКроме того, я должен отметить, что удаленный сервер использует самозаверяющий сертификат SSL. Первоначально я думал, что это может быть проблемой, поэтому я добавил сертификат в качестве доверенного корня в MMC, чтобы сертификат отображался как действительный на моей машине. Это не решило проблему.

19
задан Mike Mertsock 26 March 2012 в 13:15
поделиться