Как корректно работать с SslStream в C#?

1) Разработали сервис для выгрузки информации о проводимых торгах со сторонней площадки на госзакупки. Соединение по TLS, с двухсторонней аутентификацией.
2) На машине установлена CryptoPro 3.6, сертификат загружен в хранилище, установка соединения проходит нормально.
3) Затем отправляется xml с данными о закупке, включающими в себя закодированные в Base64 файлы с описанием закупки.
4) В случае, если приложенные к закупке файлы маленькие (менее ~7Кб), всё проходит хорошо: сервер возвращает xml с информацией о том, что всё ок.
5) А вот если файл длиной больше 7Кб, то при получении ответа от сервера падает Exception:
A call to SSPI failed, see inner exception; The message received was unexpected or badly formatted.


Проверял на разных машинах, из разных мест. Проблема точно не в канале связи.
Но есть пара непонятных для меня моментов:
1) При валидации сертификата сервера не находится корневой сертификат. В ValidateServerCertificate:
chain.ChainStatus==PartialChain Не удается построить цепочку сертификатов для доверенного корневого центра.
; RevocationStatusUnknown Функция отзыва не смогла произвести проверку отзыва для сертификата.
; OfflineRevocation Невозможно проверить функцию отзыва, т.к. сервер отзыва сертификатов недоступен .

2) После установки соединения в SslStream.LocalCertificate == null, хотя стрим создаётся с передачей userCertificateSelectionCallback:
SslStream sslStream = new SslStream(
                client.GetStream(),
                false,
                ValidateServerCertificate,
                ClientCertificateSelectionCallback);

и в методе ClientCertificateSelectionCallback локальный сертификат находится и проставляется куда следует.

Ребята, спасайте. Несколько дней бьюсь, куда копать - не ясно. С SSL раньше дела не имел, поэтому мог ошибиться где-то в элементарных вещах.
  • Вопрос задан
  • 4244 просмотра
Пригласить эксперта
Ответы на вопрос 1
gmlexx
@gmlexx
1) Скорее всего, серверный сертификат содержит всякие корявые ссылки, которые просто не позволяют вам ни нормально скачать CA(корневой), ни CRL. Посмотреть серверный сертификат не могу, т.к. у меня нет под рукой КриптоПро.
Тут решение может быть в том, чтобы где-то их найти и поставить локально (будет работать пока они не протухнут). CA обычно имеет срок действия несколько лет, CRL несколько дней или часов.
Либо не проверять совсем, либо можно ValidateServerCertificate переопределить чтобы он всегда возвращал true, и самому проверить отпечаток сертификата.

2) А зачем все так сложно то? Вроде там API требует обычный HTTP POST. Есть же более удобные абстракции, типа HttpWebRequest.

3) Ну и на крайняк, есть люди, которые уже собаку съели на взаимодействии с гос-органами. https://zakupki.kontur.ru
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы