Привет, Хабр! С вами Екатерина, React Native разработчик.

Осенью 2022 года “Сбер” объявил о переводе всех своих ресурсов на работу с применением российских сертификатов от Минцифры (ссылка на новость). Это изменение затрагивало сервис онлайн-оплаты, поэтому при планировании одного из недавних спринтов я ожидаемо увидела в своем беклоге задачу по внедрению сертификатов в мобильное приложение.

О сертификатах

Изначальной причиной перехода на российские сертификаты является то, что зарубежные компании начали отзывать сертификаты безопасности у российских сайтов. После этого МинЦифры выпустило свои собственные российские сертификаты и рекомендовало перейти на их использование. Крупные российские компании уже начали переходить на новый стандарт, и “Сбер” оказался одной из первых таких компаний.

У “Сбера” есть официальная документация для подключения сертификатов https://securepayments.sberbank.ru/wiki/doku.php/certificates:start

В документации есть инструкции по внедрению сертификатов на многие популярные платформы. Однако, инструкции для React Native приложений нет, поэтому мы искали решение самостоятельно.

Android

С Android частью приложения внедрение оказалось довольно простым. Нам нужно было скачать два сертификата с Госуслуг:

  • russian_trusted_root_ca.cer - корневой;

  • russian_trusted_sub_ca.cer - выпускающий.

Для простоты их можно переименовать в root.cer и sub.cer соответственно.

После этого, перемещаем скачанные файлы в папку project_name/android/src/res/raw. Далее нужно создать файл network_security_config.xml со следующим содержанием:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">3dsecmt.sberbank.ru</domain> //домен можно не указывать, тогда сертификаты будут работать для любых доменов 
        <trust-anchors>
            <certificates src="@raw/root"/>
            <certificates src="@raw/sub"
/>
        </trust-anchors>
    </domain-config>
</network-security-config>
Hidden text

Домен можно изменить на нужный вам или же вообще убрать (в последнем случае сертификат будет работать для любых доменов на уровне всего приложения). В нашем случае используется 3dsecmt.sberbank.ru.

Этот файл помещаем в project_name/android/src/res/xml и на этом добавление сертификатов для Android устройств будет окончено.

iOS

Перейдем к внедрению для iOS устройств.

Сначала необходимо скачать сертификат для iOS с сайта госуслуг в формате .pem. Для корректного внедрения его необходимо конвертировать в формат .der. В этом поможет следующая команда:

openssl x509 -outform der -in certificate_name.pem -out certificate_name.der

Для простоты прикладываю ссылку, где можно скачать готовый сертификат в формате .der.

Далее создаем в проекте папку Certificates и добавляем в нее конвертированный сертификат. Заходим в настройки проекта в Xcode во вкладку Build Phase и добавляем в Cope Bundle Resource наш сертификат.

На нашем проекте мы используем библиотеку react-native-webview для отображения страницы оплаты в мобильном приложении. Мы воспользовались методом из библиотеки setCustomCertificatesForHost, который предназначен для добавления сертификатов в приложение.

Таким образом, в файле AppDelegate.m, нужно изменить метод didFinishLaunchingWithOptions. В него добавляем следующий код:

  // Get the bundle where the certificates in DER format are present.
  NSBundle *bundle = [NSBundle mainBundle];

  NSMutableDictionary* certMap = [NSMutableDictionary new];

  NSData *rootCertData = [NSData dataWithContentsOfFile:[bundle pathForResource:@"Russian Trusted Root CA" ofType:@"der"]];

  SecCertificateRef certificate = SecCertificateCreateWithData(NULL, (CFDataRef) rootCertData);

  OSStatus err = SecItemAdd((CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:(id) kSecClassCertificate, kSecClass, certificate, kSecValueRef, nil], NULL);

  [certMap setObject:(__bridge id _Nonnull)(certificate) forKey:@"3dsec.sberbank.ru"];

  [RNCWebView setCustomCertificatesForHost:certMap];

Не забудьте изменить путь к сертификату, если у вас он отличается от приведенного.

На этом внедрение сертификатов для iOS устройств окончено.

Спасибо за внимание и желаю удачи с внедрением сертификатов в ваши приложения!