Pull to refresh
РСХБ.цифра (Россельхозбанк)
Меняем банк и сельское хозяйство

Flutter и ГОСТ TLS

Level of difficultyMedium
Reading time9 min
Views3.5K

Меня зовут Куприёв Андрей, я Flutter‑разработчик в команде Центра развития финансовых технологий (ЦРФТ) Россельхозбанка. В этой статье мы рассмотрим, как реализовать поддержку протокола ГОСТ TLS в приложениях, разработанных на Flutter.

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

TLS: Краткий обзор

Протокол TLS (Transport Layer Security) представляет собой один из наиболее широко используемых механизмов для установления защищенного канала связи. Основанный на спецификации SSL (Secure Sockets Layer) версии 3.0, TLS претерпел значительные изменения за время своего развития. В настоящее время актуальной является версия TLS 1.3, хотя TLS 1.2 остается наиболее распространенной.

Основная задача TLS заключается в создании безопасного канала между клиентом и сервером для гарантирования целостности и конфиденциальности передаваемых данных. Протокол использует различные криптографические алгоритмы на различных этапах своей работы. Эти алгоритмы определяются криптонабором, который представляет собой совокупность алгоритмов, определенных в стандартизирующих документах. Стороны согласовывают используемый криптонабор в начале установки защищенного канала.

Что такое ГОСТ TLS

ГОСТ TLS использует российские криптографические алгоритмы в рамках криптонаборов протокола TLS.

В контексте криптографии аббревиатура «ГОСТ» используется для обозначения российских государственных криптографических стандартов. Эти стандарты определяют алгоритмы шифрования, хэширования, электронных подписей и другие криптографические методы, которые применяются в России для обеспечения безопасности информации.

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

Какие стандарты используются в ГОСТ TLS?

  • ГОСТ Р 34.10–2012 Стандарт определяет алгоритмы формирования и проверки электронной цифровой подписи. Эти алгоритмы применяются для обеспечения аутентификации и подписи сообщений. (ИСО 2382–2 [1], ИСО/МЭК 9796 [2]‑[3], ИСО/МЭК 14 888 [4]‑[7] и серии ИСО/МЭК 10 118 [8]‑[11]).

  • ГОСТ Р 34.11–2012 Стандарт определяет алгоритмы хэширования. Эти алгоритмы используются для создания хэшей данных и обеспечения целостности передаваемых сообщений. (ИСО 2382–2 [1], ИСО/МЭК 9796 [2–3], серии ИСО/МЭК 14 888 [4–7] и серии ИСО/МЭК 10 118 [8–11]).

  • ГОСТ Р 34.12–2015 Стандарт определяет алгоритмы блочного шифрования, включая ГОСТ 34.12–2015/256, ГОСТ 34.12–2015/512. Эти алгоритмы применяются для шифрования данных в ГОСТ TLS. (ИСО/МЭК 10 116 и серии ИСО/МЭК 18 033).

  • ГОСТ Р 34.13–2015 Стандарт определяет режим работы блочных шифров. Данные режимы работы блочных шифров определяют правила криптографического преобразования данных и выработки имитовставки для сообщений произвольного размера. (ИСО/МЭК 9797–1 [1], ИСО/МЭК 10 116 [2], ИСО/МЭК 10 118–1 [3], ИСО/МЭК 18 033 [4], ИСО/МЭК 14 888–1 [5]).

Эти стандарты являются ключевыми компонентами ГОСТ TLS и обеспечивают криптографические операции, необходимые для аутентификации, шифрования и обеспечения целостности данных в рамках данного протокола.

Как выглядит реализация ГОСТ TLS для Android

В случае с Android, есть возможность использовать криптопрвайдеры, например от компании Крипто Про (Крипто Про CSP), который поставляет реализацию ГОСТ алгоритмов. Благодаря архитектуре JCA (Java Cryptography Architecture) можно свободно интегрировать этот криптопровайдер для использования в TLS.

При установлении соединения существует два способа определения параметров аутентификации, это использование динамического или статического SSLContext (с применением System.setProperty и параметров из пакета javax.net.ssl.*).

SSLContext является частью JSSE (Java Secure Socket Extension). SSLContext представляет собой основной класс в JSSE, который используется для создания и настройки SSL/TLS сессий. Этот класс позволяет приложениям управлять параметрами безопасности, такими как протоколы шифрования, сертификаты и параметры аутентификации.

Таким образом, SSLContext является ключевым компонентом JSSE, который обеспечивает основу для защищенного сетевого взаимодействия в Java. JSSE в целом предоставляет набор API для реализации безопасности сокетов, а SSLContext является основным инструментом для создания и управления SSL/TLS соединениями в Java‑приложениях.

Статический контекст устанавливается один раз на весь java‑процесс, и является опциональным, вот пример настройки:

Security.setProperty("ssl.KeyManagerFactory.algorithm", "GostX509"); // ГОСТ алгоритм
Security.setProperty("ssl.TrustManagerFactory.algorithm", "GostX509"); // ГОСТ алгоритм
Security.setProperty("ssl.SocketFactory.provider", "ru.CryptoPro.ssl.SSLSocketFactoryImpl"); // задаем реализацию сокетов с ГОСТ алгоритмами
Security.setProperty("ssl.ServerSocketFactory.provider", "ru.CryptoPro.ssl.SSLServerSocketFactoryImpl"); // задаем реализацию сокетов сервера с ГОСТ алгоритмами
System.setProperty("javax.net.ssl.trustStore", "path_to_trust_store"); // хранилище сертификатов
System.setProperty("javax.net.ssl.trustStoreType", "CertStore"); // может быть другой тип
System.setProperty("javax.net.ssl.trustStoreProvider", "JCP"); // может быть другой провайдер
System.setProperty("javax.net.ssl.trustStorePassword", "password_to_trust_store");
System.setProperty("javax.net.ssl.keyStore", ""); // тут может быть алиас ключа
System.setProperty("javax.net.ssl.keyStoreType", "HDIMAGE"); // может быть другой тип
System.setProperty("javax.net.ssl.keyStoreProvider", "JCSP"); // может быть другой провайдер
System.setProperty("javax.net.ssl.keyStorePassword", "password_to_key"); // пароль к ключу
System.setProperty("ngate_set_jcsp_if_gost", "true"); // для работы в режиме Knox на Samsung задаем провайдер Java CSP в качестве провайдера по умолчанию

Динамический контекст создается без участия настроек из группы javax.net.ssl.*, лишь с помощью классов пакета javax.net.ssl.*, например:

KeyStore ts = KeyStore.getInstance("CertStore", "JCP");
ts.load("trust_store_stream", "trust_store_password"); // хранилище корневых сертификатов
KeyManagerFactory kmf = KeyManagerFactory.getInstance("GostX509", "JTLS");
if (isClientAuth) { // если требуется клиентская аутентификация
    // параметры хранилища ключей клиента
    KeyStore ks = KeyStore.getInstance("HDIMAGE", "JCSP");
    // явное указание контейнера
    if (haveKeyAlias) { // можно ли указать алиас?
        ks.load(new StoreInputStream("key_alias"), null); // алиас ключа
    } // if
    else {
        ks.load(null, null);
    } // else
    kmf.init(ks, password_to_key); // пароль к ключу
} // if
TrustManagerFactory tmf = TrustManagerFactory.getInstance("GostX509", "JTLS");
tmf.init(ts);
SSLContext context = SSLContext.getInstance("GostTLSv1.2", "JTLS"); // протокол TLS v.1.2
context.init(isClientAuth ? kmf.getKeyManagers() : null, tmf.getTrustManagers(), null);

В дальнейшем, созданный контекст можно передать в соответствующую реализацию https‑соединения, такую как HttpsURLConnection, OkHttp, Apache Http Client 5 и другие. Все эти библиотеки в разной степени принимают объект класса SSLContext, хотя более распространенным вариантом является передача объекта класса SSLSocketFactory, полученного из SSLContext.

Основное отличие между этими способами в том, что если к примеру в первом случае установив статический контекст вы попробуете обратиться к серверу, который не поддерживает ГОСТ TLS, то вы не сможете установить соединение. Это можно сделать с помощью второго способа. Вы можете настроить сетевые клиенты своих библиотек и использовать один сетевой клиент, настроенный для ГОСТ TLS‑ соединения, а другой для обычного TLS соединения.

Предварительно, чтобы использовать Крипто Про CSP у себя в Android приложении, его нужно подключить, настроить и инициализировать. Разместить файлы библиотеки в папке libs, подключить и настроить их в build.gradle, и проинициализировать, вызвав метод CSPConfig.init(this).

Метод init() выполняет начальную настройку провайдера в контексте приложения, включая создание каталогов, копирование и проверку файлов лицензии и конфигурации, а также формирование доверенного хранилища BKS в папке security приложения и другие необходимые действия

Подробное описание этого процесса есть в руководстве Крипто Про CSP.

Алгоритмы поддерживаемые Крипто Про CSP

  • Электронная подпись: ГОСТ Р 34.10–2012 (ГОСТ 34.10–2018), ECDSA, RSA.

  • Хэш‑функции: ГОСТ Р 34.11–2012 (ГОСТ 34.11–2018), SHA-1, SHA-2.

  • Шифрование: ГОСТ Р 34.12–2015 (ГОСТ 34.12–2018), ГОСТ Р 34.13–2015 (ГОСТ 34.13–2018), ГОСТ 28 147–89, AES (128/192/256), 3DES, 3DES-112, DES, RC2, RC4.

Как выглядит реализация ГОСТ TLS под iOS с использованием Крипто Про CSP

Для обеспечения поддержки ГОСТ TLS под iOS с помощью Крипто Про CSP предлагается использовать свою имплементацию библиотеки libcurl. Эта библиотека является инструментом для работы с сетью, а ее интеграция с Крипто Про CSP позволяет осуществить взаимодействие с протоколом ГОСТ TLS.

Основные задачи, связанные с работой протокола по ГОСТ TLS, берет на себя библиотека libcurl. Для отправки запросов в сеть мы должны сформировать запрос curl и отправить его, а затем обработать полученный ответ.

Для указания использования ГОСТ TLS для libcurl от Крипто Про CSP необходимо установить определенные опции:

curl_easy_setopt(curlHandle, CURLOPT_STRICT_GOST, 1L);
curl_easy_setopt(curlHandle, CURLOPT_NOPROXY, "*");
curl_easy_setopt(curlHandle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS);
curl_easy_setopt(curlHandle, CURLOPT_SSL_VERIFYPEER, 1);

Эти опции позволяют настроить libcurl на использование ГОСТ TLS.

В общем виде реализация ГОСТ TLS под iOS с использованием Крипто Про CSP выглядит следующим образом:

 Подключаем библиотеку Крипто Про CSP в iOS-приложение. (Процесс интеграции подробно описан в документации).

Создаем реализацию отправки сетевого запроса через libcurl с учетом ГОСТ TLS.

Создаем API для Swift/Objective-C для удобства использования этого запроса в iOS-приложении.

А как же Flutter?

А Flutter вместе с Dart ничего не знают о ГОСТ алгоритмах, они не знают об этих стандартах и протоколах. Поэтому использовать их где‑либо у себя по умолчанию никак не могут. Кроме того, в Dart/Flutter нет и крипто архитектуры наподобие JCA (Java Cryptography Architecture), где мы могли бы использовать свой криптопровайдер, поставляющий реализацию ГОСТ алгоритмов, подключив который, мы смогли бы использовать эти алгоритмы.

Возможным вариантом использования ГОСТ TLS в Flutter является нативная реализация ГОСТ TLS отдельно на Android и отдельно на IOS, с использованием платформенных каналов для двусторонней передачи данных условно от Flutter/Dart к Android (Java, Kotlin) и IOS (Swift/Objective‑C).

Собственно говоря, для внутреннего использования в своих проектах мы пошли по этому пути. По пути создания плагина. Имплементировали реализацию ГОСТ TLS на Android и IOS. С помощью платформенных каналов реализовали двустороннюю передачу данных. Для простоты внедрения в любые проекты создали реализацию своего http‑клиента и Dio адаптера. Что в итоге позволило свести подключение библиотеки и внедрение ГОСТ TLS в свой проект к нескольким строкам кода. Это подключение зависимости плагина в pubspec.yml проекта, и подключение Dio адаптера к нашему клиенту Dio.

В Flutter/Dart экосистеме существует довольно много пакетов, которые принимают на вход пользовательские сетевые клиенты http. Так вот, в этом случае эти пакеты начинают использовать ГОСТ TLS внутри себя, даже не замечая этого, благодаря использованию «гостового» http клиента, реализованного в плагине. Так, например, произошло у нас с пакетом matrix_api_lite, который мы используем для нашего внутреннего корпоративного мессенджера. Мы просто передали наш http клиент из плагина в конструктор MatrixApi (благо его реализация это позволяла), и он стал работать по ГОСТ TLS без каких‑либо доработок и форков.

Заключение

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

Tags:
Hubs:
Total votes 21: ↑20 and ↓1+19
Comments5

Articles

Information

Website
www.rshb.ru
Registered
Founded
Employees
over 10,000 employees
Location
Россия
Representative
Юлия Князева