Нажимая кнопку «Отправить», вы принимаете правилами обработки персональных данных
Заявка отправлена

Спасибо за проявленный интерес к нашей компании, специалист свяжется с вами в ближайшее время

Услуги
Веб-разработка
Разработка мобильных приложений
Автоматизация бизнеса
UX/UI дизайн
Техподдержка интернет-проектов 24/7 по SLA
Digital-продвижение
Обработка данных
Наша работа
Кейсы
Нажимая кнопку «Отправить», вы принимаете правилами обработки персональных данных
Заявка отправлена

Спасибо за проявленный интерес к нашей компании, специалист свяжется с вами в ближайшее время

Интеграция .NET-приложения с внешним API по ГОСТ TLS через CryptoPro

< Все публикации
август 2025 ~ 19 минИсточник Habr
Евгений Думчев

Всем привет. Представлюсь — меня зовут Евгений Думчев и я Team Lead .NET разработки в DDPlanet.

В какой-то момент в моей практике появилась задача по интеграции с внешним API. Для взаимодействия требовалось применять предоставленный публичный доверенный сертификат сервера .cer и клиентский .pfx сертификат. Особенность в том, что .pfx сертификат был выпущен через CryptoPro CSP — а это вносит свои тонкости в процесс интеграции.

В этой статье я расскажу, как интегрировать .NET-приложение с внешним API, требующему двусторонней TLS-аутентификации по национальным криптографическим стандартам (ГОСТ) с использованием сертификатов, выпущенных через CryptoPro CSP.

Безопасность и сферы применения двустороннего TLS с CryptoPro

При работе с государственными или банковскими API в РФ часто предъявляются требования к применению национальных криптографических стандартов. В таких случаях сертификаты формируются через CryptoPro CSP и содержат ГОСТ-алгоритмы, которые отличают эти сертификаты от обычных X.509 сертификатов, применяемых в международной практике.

Более того, для повышения уровня безопасности при взаимодействии по API может применяться двусторонняя TLS-аутентификация (mTLS), которая обеспечивает повышенный уровень доверия между клиентом и сервером. Это означает, что:

  1. Сервер предоставляет свой сертификат — клиент проверяет, доверять ли серверу.
  2. Клиент предъявляет свой сертификат (client certificate) — сервер проверяет его подлинность.

Работает это по следующему принципу:

  • При вызове внешнего API, клиент (в нашем случае .NET Web API приложение) выполняет запрос соединения с сервером.
  • В процессе TLS-рукопожатия сервер отсылает клиенту свой публичный сертификат.
  • Клиент проверяет валидность публичного сертификата, сравнивая его с заранее известным и доверенным сертификатом сервера (например, .cer файлом) или по цепочке доверия к корневому УЦ. Если сертификат соответствует ожидаемому, то можно доверять этому серверу.
  • Так как на стороне сервера включена двусторонняя аутентификация — он отправляет запрос о необходимости предоставления клиентского сертификата.
  • Клиент отправляет публичный сертификат (и при необходимости цепочку) из контейнера .pfx и подтверждает владение приватным ключом из контейнера .pfx.
  • Сервер проверяет подпись и цепочку доверия, а также сверяет, выдан ли сертификат от доверенного УЦ.
  • Если все проверки пройдены успешно — устанавливается защищенное соединение — API становится доступным и клиенту можно выполнять обработку запросов.

Сертификат .pfx (Personal Information Exchange) применяется из соображений безопасности. Это стандартизированный двоичный формат контейнера сертификатов PKCS #12 (Public-Key Cryptography Standards). Он представляет собой единый файл, который включает в себя закрытый ключ (private key), открытый ключ / сертификат (public key) и цепочку доверия (промежуточные и корневые сертификаты). К особенностям можно отнести то, что содержимое .pfx-файла шифруется и защищается паролем.

Дополнительно .pfx-файл может быть экспортирован с включенной опцией «расширенной защиты», что позволяет повысить уровень безопасности хранения закрытого ключа внутри контейнера. Это достигается посредством применения более стойкого шифрования и добавления ограничения на экспорт — даже после импорта сертификата его нельзя будет снова выгрузить с приватным ключом.

Получаем следующую схему взаимодействия:

1.png

С таким уровнем безопасности с применением CryptoPro чаще всего можно столкнуться при взаимодействии с отечественным ПО в следующих сферах:

  • Системы электронного документооборота (ЭДО).
  • Порталы государственных услуг.
  • Банковские и финансовые API.
  • Торговые площадки, работающие с ЭЦП (электронной подписью).
  • Юридически значимые интеграции — в которых важно соблюдение требований к квалифицированной электронной подписи (КЭП).

Особенности взаимодействия с API, использующим сертификат CryptoPro

При взаимодействии со сторонней API по REST в нашем случае должен использоваться .pfx сертификат, созданный через CryptoPro. Это означает, что алгоритмы и структуры сертификата могут содержать специфичные для ГОСТ и CryptoPro криптографические идентификаторы OID, например, 1.2.840.113549.1.12.1.80, которые не поддерживаются большинством стандартных библиотек (например, OpenSSL, curl). Что требует использования именно CryptoPro или его оберток для корректной работы.

У сторонней API предусмотрена Swagger-документация, но она так просто не доступна в браузере.

Во-первых, для доступа к API из браузера необходимо установить CryptoPro CSP. Этот инструмент позволяет установить на устройство клиентский сертификат .pfx.

Во-вторых, даже после установки сертификата Swagger-документация внешнего API становится доступна только в браузерах Chromium-Gost и Яндекс Браузер. Эти браузеры поддерживают отечественные криптографические алгоритмы ГОСТ, используемые в сертификатах, выпущенных через CryptoPro. И на этих браузерах должен быть установлен КриптоПро ЭЦП Browser Plugin.

Наконец, при открытии url /swagger в подходящем браузере появляется модальное окно CryptoPro CSP для выбора нужного сертификата, применяемого для доступа к ресурсу. И после выбора нужного сертификата — победа, Swagger-документация становится доступна и позволяет успешно отправлять REST запросы на сервер.

Но как же выполнять взаимодействие с API по REST из приложения на .NET? Ведь в случае классической реализации выполнения запросов через HttpClient получаем в ответе HTTP статус код 400 (Bad Request) с ошибкой:

2.png

Основным решением является подключение к запросам клиентского сертификата .pfx CryptoPro и публичного доверенного сертификата сервера .cer для организации двусторонней TLS-аутентификации.

Рассмотрим следующие варианты решения:

  • для .NET приложения, запускаемом на Windows;
  • для .NET приложения, запускаемом на Linux;
  • с помощью NGINX.

Решение для .NET приложений в Windows

Самый простой способ подцепить сертификаты (клиентский .pfx и доверенный сертификат сервера .cer) из приложения на .NET под Windows заключается в том, чтобы добавить их в виде файлов в структуру проекта.

3.png

После чего эти файлы можно подгрузить по пути к ним и применить в REST запросах к целевой API. Для этого необходимо сконфигурировать типизированный HttpClient и добавить к обработке HTTP запросов логику применения сертификатов в HttpClientHandler.

4.png

После запуска приложения и выполнения целевого запроса вызывается криптопровайдер CryptoPro CSP и появляется всплывающее окно запроса пароля. Такое поведение проявляется при использовании сертификатов с пометкой «требовать защищенную сессию». В этом случае CryptoPro всегда запрашивает ввод пароля или подтверждение доступа, даже если вы уже указали пароль при загрузке X509Certificate2.

5.png

После указания учетных данных запросы успешно доходят до целевого API.

Но в данном случае появляется проблема в виде всплывающего окна установки контейнера с паролем, что блокирует работу приложения.

Можно воспользоваться альтернативным вариантом и предварительно установить все эти сертификаты на устройство и искать целевые сертификаты из хранилища сертификатов.

Правильнее проводить поиск сертификатов в хранилище по Thumbprint (отпечатку) — это считается наиболее надежным и безопасным способом идентификации сертификатов в хранилище. По сути, это уникальный SHA-1 хэш содержимого сертификата, который гарантирует точное совпадение и устойчивость к дубликатам.

Тогда получим следующий код:

6.png

В данном случае сертификат CryptoPro успешно достается из хранилища сертификатов Windows и применяется в запросах на сервер без всплывающего окна и запроса пароля. Это работает за счет того, что криптопровайдер CryptoPro интегрируется в инфраструктуру Windows как один из поддерживаемых провайдеров. Соответственно, сертификаты, установленные через CryptoPro, регистрируются в стандартных хранилищах Windows — например, в StoreName.My и StoreLocation.CurrentUser или LocalMachine и доступны через X509Store.

Решение для .NET приложений в Linux

Для запуска приложения в Linux соберем и запустим docker образ.

7.png

Если воспользоваться логикой подключения сертификатов напрямую из структуры проекта, то при запуске получим ошибку:

8.png

Ошибка возникает из-за того, что OpenSSL не может корректно прочитать сертификат, поскольку в нем используется алгоритм шифрования от CryptoPro, который не поддерживается в стандартной сборке OpenSSL. То есть в Linux такой сертификат не типизировать в X509Certificate2, как это работало для Windows «из коробки».

Установить сертификат на Linux с помощью команд OpenSSL не получится - формат PFX сертификатов не поддерживается в операционной системе Linux. Однако есть возможность конвертировать его в формат PEM с помощью OpenSSL:

9.png

Также можно попытаться разобрать .pfx на составляющие, что небезопасно, так как приватный ключ будет в незашифрованном виде:

10.png

Все это не сработает для .pfx сертификата CryptoPro по причине неизвестного алгоритма шифрования.

11.png

Одним из вариантов решения является установка модифицированной версии OpenSSL, например, gost-engine. Но я бы не рекомендовал подобный вариант, так как сторонние реализации не гарантируют поддержку и безопасность, а также могут не поддерживать актуальные сертификаты или ключи.

Правильным вариантом решения является использование сертифицированного CryptoPro CSP для Linux. И установить его в docker-образ. Скачать необходимый дистрибутив можно по ссылке. В нашем случае используется образ mcr.microsoft.com/dotnet/aspnet:8.0, который базируется на debian образе, поэтому нужно установить дистрибутив linux-amd64_deb.tgz.

CryptoPro CSP является набором инструментов по работе с криптографией, предназначенных для реализации российских алгоритмов ГОСТ, создания и проверки электронной подписи, шифрования, управления сертификатами и контейнерами закрытых ключей. Часть полезных инструментов, содержащихся в сборке linux-amd64_deb.tgz:

  • csptest — инструмент для тестирования функций CSP: проверка алгоритмов, ключей, сертификатов, подписей и шифрования.
  • certmgt — утилита управления сертификатами: установка, удаление, экспорт и просмотр сертификатов из хранилищ CSP.
  • cprodiag — диагностический инструмент для сбора информации о конфигурации CryptoPro CSP, лицензии, хранилищах и возможных ошибках.
  • cpverify — проверка целостности и корректности установки CryptoPro CSP: сверка контрольных сумм и доступности компонентов.
  • cryptcp — утилита для подписания, шифрования и проверки данных.
  • cpconfig — утилита настройки компонентов CryptoPro CSP: используется для активации и просмотра лицензий, управления параметрами криптопровайдера и системными настройками.
  • cpnginx — модифицированная версия NGINX с поддержкой ГОСТ TLS через интерфейс SSPI, встроенная в CryptoPro CSP.

Внесем изменения в Dockerfile — добавим команды по установке CryptoPro CSP. Для соблюдения правил использования необходимо указать лицензионный ключ. И с помощью инструментария CryptoPro CSP нужно установить сертификаты .pfx и .cer. Скорректированный Dockerfile:

12.png

После выполнения команды установки сертификата .pfx его содержимое импортируется в систему CryptoPro и преобразуется — разбивается на отдельные компоненты, сохраненные в формате с расширением .key:

13.png

В основном хранилище ключей keys появляется наш преобразованный .pfx контейнер в формате cert.000 с шестью файлами:

  • primary.key, primary2.key — основные ключи.
  • name.key — содержит имя или идентификатор контейнера.
  • masks.key, masks2.key — используется для маскировки/шифрования ключей.
  • header.key — содержит метаинформацию (заголовок, версию и т. п.).

Поскольку в Linux .pfx сертификат CryptoPro не типизировать в X509Certificate2, то ни вариант с загрузкой сертификата напрямую из структуры проекта, ни вариант с получением из хранилища сертификатов X509Store не сработает — нам не удастся найти целевой .pfx сертификат и, соответственно, не получится выполнить TLS-рукопожатие. Получим следующую ошибку:

14.png

В Linux предусмотрена возможность получения сертификатов из специализированного хранилища сертификатов CryptoPro. Для этого необходимо воспользоваться официальным кроссплатформенным решением CryptoPro .NET, доступным по ссылке.

Решение включает в себя четыре NuGet-пакета, которые необходимо подключить к проекту. Это можно сделать одним из следующих способов:

Локальное подключение пакетов.

Загрузка пакетов в онлайн-репозиторий, например Nexus, Azure DevOps и другие.

В .csproj нужно добавить все эти пакеты:

15.png

Теперь с помощью библиотек CryptoPro можно получить сертификаты с типом CpX509Certificate2 из хранилища сертификатов CpX509Store. Получим следующий код:

16.png

В данном случае сертификат CryptoPro успешно достается из хранилища сертификатов CryptoPro и применяется в запросах на сервер. Вдобавок это решение работает и для Windows тоже.

Решение с помощью NGINX

Вместо интеграции ГОСТ TLS напрямую в .NET-приложение, можно вынести TLS-обвязку на уровень NGINX. Это снимает с .NET приложения (или приложения на любом другом языке программирования) необходимость подключения CryptoPro-сертификатов и реализации TLS взаимодействия, что упрощает код, повышает кроссплатформенность и масштабируемость решения.

Чтобы это работало с сертификатом CryptoPro необходимо воспользоваться cpnginx — специальной версией NGINX от CryptoPro с поддержкой ГОСТ TLS. Это решение содержится в linux-дистрибутивах, доступных на официальной странице загрузки CryptoPro CSP.

Получаем следующую схему взаимодействия с внешним API:

17.png

Таким образом:

  • .NET-приложение посылает обычные HTTP-запросы на cpnginx;
  • cpnginx выступает в роли клиента TLS, обрабатывая криптографию через CryptoPro CSP;
  • cpnginx проксирует запрос на сервер и возвращает ответ приложению.

Для настройки CryptoPro Nginx необходимо создать внешний конфигурационный файл api-tls.conf. Этот конфиг необходимо поместить в директорию /etc/opt/cprocsp/cpnginx/conf.d/api-tls.conf. Все *.conf-файлы из этой директории автоматически подключаются к основному конфигурационному файлу cpnginx.

18.png

Для запуска cpnginx приложения в Linux соберем и запустим docker образ:

19.png

NGINX успешно запускается и принимает входящие HTTP-запросы на http://localhost:8080 (настраивается) и проксирует их на внешний API с использованием CryptoPro TLS. Все запросы и ошибки логируются в /var/log/cpnginx/access.log и /var/log/cpnginx/error.log.

В приложении .NET конфигурация HttpClient упрощается. Остается только указать адрес nginx - куда посылать запросы:

20.png

Получаем решение, которое обладает следующими преимуществами:

  • Упрощение .NET-приложения — нет необходимости подключать и настраивать ГОСТ TLS в приложении. ‑TLS реализован на nginx.
  • Независимость от языка программирования приложения.
  • Изоляция криптографии — CryptoPro CSP используется только внутри контейнера cpnginx.
  • Легкое масштабирование — cpnginx можно масштабировать независимо от самого приложения.

Как безопасно хранить сертификаты и пароли к ним

При работе с чувствительными данными, особенно такими как.pfx сертификаты с приватным ключом, крайне важно соблюдать правила безопасного хранения. На этапе разработки многие допускают ошибку — хранят сертификаты и пароли в открытом виде прямо в проекте, включая их в git‑репозиторий или конфигурационные файлы. Это недопустимо даже в условиях ограниченного доступа к репозиторию.

Правильным подходом является хранение сертификатов и секретов вне исходного кода. Кроме того, сертификаты не должны включаться в Docker‑образ напрямую. Вместо этого они монтируются во время запуска контейнера через Docker volume или persistent volume в Kubernetes. Пароли к ним считываются в runtime, не попадая в историю образа.

Для исключения чувствительных данных можно воспользоваться следующими безопасными механизмами хранения:

  • Переменные окружения, определенные в CI/CD или на хост‑машине при запуске.
  • Secrets‑хранилища: например, Azure Key Vault, AWS Secrets Manager, HashiCorp Vault.
  • Docker Secrets / Kubernetes Secrets — для защищенной передачи секретов в контейнеры.

Такой подход позволяет обеспечить высокий уровень безопасности на всех этапах жизненного цикла приложения - от сборки до развертывания в production среде.

Заключение

Интеграция с API, использующим сертификаты CryptoPro и ГОСТ TLS, может показаться непростой задачей, особенно в кроссплатформенных проектах. В статье рассмотрено три рабочих варианта: реализацию для.NET‑приложений на Windows и на Linux, а также подход с использованием cpnginx — модифицированного NGINX с поддержкой ГОСТ TLS.

Наиболее универсальным и масштабируемым решением становится cpnginx. Он полностью изолирует криптографическую обвязку от логики приложения, устраняет зависимость от ОС, упрощает сопровождение и снижает риски, связанные с безопасностью. С его помощью.NET‑приложение может работать с API как с обычным HTTP‑сервисом, а все криптографические операции выполняются внутри защищённого контейнера.

Все решения применимы на практике. Выбор подхода зависит от ваших потребностей, ограничений, инфраструктуры и требований безопасности.

Связаться с нами
Форматы: jpg, png, xls, xlsx, doc, docx, pdf
Размер до 5 МБ
Нажимая кнопку «Отправить», вы принимаете правилами обработки персональных данных
Заявка отправлена

Спасибо за проявленный интерес к нашей компании, специалист свяжется с вами в ближайшее время