Встраивание КриптоПро Ключ SDK в мобильное приложение (iOS)
Руководство по встраиванию содержит перечень действий, необходимых для встраивания КриптоПро Ключ SDK в собственное мобильное приложение.
Инструкция предназначена для разработчиков мобильных приложений для iOS версии 13 и новее, использующих фреймворк разработки пользовательских интерфейсов UI Kit. Требуется Xcode 11 и macOS 10.15 или новее. Рекомендуется использовать последние версии перечисленного программного обеспечения.
Добавление необходимых файлов в проект
1. Перенести в папку Frameworks Вашего проекта полученный фреймворк с КриптоПро Ключ SDK DSSFramework.xcframework
.
- В XCode перенести в папку Frameworks c выбранной опцией Create folder references.
- Открыть
DSSFramework.xcframework
как папку через Finder и также перенестиDSSFrameworkSupport.xcframework
в папку Frameworks с аналогичной опцией.
2. Открыть DSSFramework.xcframework
как папку через Finder
и оттуда перенести папку Scripts в корневую папку Вашего проекта.
Примечание
Корневой папкой будем называть главную папку проекта,
где лежат файлы проекта XCode .xcodeproj
(.xcworkspace
) и/или папку,
относительно которой идет работа с git.
3. В Xcode из DSSFramework.xcframework
перенести файл AppControl.c
в папку, где лежат файлы приложения-клиента.
Например, у корневой папки SignIt есть внутри одноименная папка SignIt, где
лежат файлы AppDelegate
и прочие.
При копировании необходимо использовать следующие параметры.
4. В Xcode в DSSFramework.xcframework
открыть папку CSP и перетащить папки
en.lproj
и ru.lproj
в папку Resources.
При копировании необходимо использовать следующие параметры.
После добавления папок их иконки в XCode слева должны быть серого цвета.
5. В Xcode в DSSFramework.xcframework
из папки CSP перенести оставшиеся
файлы в папку Resources Вашего проекта.
При копировании необходимо использовать следующие параметры.
Итоговый результат должен выглядеть следующим образом.
*6. Настройка правил сборки в случае использования Xcode 16 и новее: изменить параметр Build Rules
для папки locale
. По умолчанию параметр равен Apply to Each File.
Необходимо установить значение параметра Apply Once to Folder, выбрав его из выпадающего списка (1, 2).
После установки значения необходимо убедиться, что папка включена в необходимые для сборки Target Membership Вашего проекта (3).
Настройка проекта
1. Открыть настройки Вашего проекта и выбрать свое приложение в Targets.
Во вкладке General открыть опцию "Frameworks, Libraries, and Embedded Content"
и напротив DSSFramework.xcframework
выбрать опцию Embed & Sign.
2. Открыть настройки Вашего проекта и выбрать свое приложение в Targets.
Во вкладке Build Phases открыть опцию Run Script.
Удалить все, что там было до этого, и добавить следующую строку:./Scripts/ConfigureApplication
.
Примечание
Необходимо убедиться, что файлы в папке Scripts
не находятся в карантинной зоне macOS.
3. Открыть настройки Вашего проекта и выбрать свое приложение в Targets.
Во вкладке Build Settings открыть опцию Build Options.
В ней установить значение User Script Sandboxing
равным No
.
Это необходимо, чтобы была возможность выполнять дополнительные исполняемые файлы при сборке проекта.
Активация контроля целостности мобильного приложения
Примечание
Выполнение этого пункта является обязательным, но не позволит пользоваться Canvas для предпросмотра UI. Допустимо выполнить шаги данного пункта после разработки UI мобильного приложения. См. подробнее в документации по встраиванию КриптоПро CSP для iOS
1. Во вкладке Build Settings открыть опцию Build Options.
В ней установить значение Enable Debug Dylib
равным No
.
2. В коде собственного мобильного приложения объявить метод контроля целостности:
@_silgen_name("register_app_checksum")
func registerAppChecksum()
Примечание
Необходимо убедиться, что в дистрибутиве SDK в файле AppControl.c
есть объявление метода
register_app_checksum
.
3. Вызвать метод registerAppChecksum
при запуске собственного мобильного приложения для вычисления
эталонной контрольной суммы приложения и метод checkIntegrity
для ее проверки.
По умолчанию контроль целостности выполняется автоматически для SDK каждые 10 минут. Выполнение данного пункта дополнительно активирует автоматический контроль целостности мобильного приложения каждые 10 минут. В случае если хотя бы один из модулей (SDK или приложение) не пройдет автоматический контроль целостности, будет отключена возможность использования криптографических функций, что делает невозможным установление защищенного соединения с сервером, подпись, подтверждение операций и т.д.
Подробнее о контроле целостности
Инициализация SDK
Для загрузки SDK в составе собственного приложения рекомендуется вызывать сразу после запуска или при запуске приложения следующий код:
SDKFramework.shared._init() { res in
var message: String = "Инициализация SDK"
switch res {
case .init_ok:
//MARK:- Успешная инициализация
message = "SDK успешно инициализирован"
case .init_lockScreen_not_installed:
//MARK:- На устройстве не настроен экран блокировки
message("SDK инициализирован")
case .init_certs_not_installed:
//MARK:- Корневые сертификаты не установлены
message = "Ошибка инициализации SDK"
case .init_device_rooted:
//MARK:- Устройство имеет права суперпользователя
message = "Ошибка инициализации SDK"
}
print(message)
}
Интеграция с UI собственного приложения
В SDK предусмотрено взаимодействие с пользователем, поэтому для работы пользовательского интерфейса
необходимо реализовать протокол DSSNavigationDelegate
. Он отвечает за “стыковку” интерфейса приложения,
куда встраивают SDK, и веб-интерфейса самого SDK.
Описание протокола
@MainActor
public protocol DSSNavigationDelegate: AnyObject {
/// Показ форм SDK
/// - Parameters:
/// - navigationController: NavigationController, который необходимо отобразить, желательно на UIWindow
/// - animated: нужна ли анимация?
/// - completion: завершения события показа
func needShow(navigationController: DSSNavigationController, animated: Bool, completion: @escaping (() -> Void))
/// Закрытие форм SDK
/// - Parameters:
/// - navigationController: NavigationController, который необходимо спрятать (должен соответствовать needShow)
/// - animated: нужна ли анимация?
/// - completion: завершения события закрытия
func needHide(navigationController: DSSNavigationController, animated: Bool, completion: @escaping (() -> Void))
/// Требование показа модального экрана сетевой активности
func needShowLoading()
/// Требование закрытия модального экрана сетевой активности
func needHideLoading()
}
Примечание
- В методах
needShow
/needHide
параметрnavigationController
– это объект подкласса от UINavigationController, отвечающий за UI в SDK. - Методы
needShow
/needHide
вызывается самим SDK при его необходимости отобразить/закрыть пользовательский интерфейс. - В методе
needShow
SDK передает свойnavigationController
, который необходимо отобразить в данный момент.
Описанный выше протокол необходимо встроить в место взаимодействия собственного приложения с UI, например, в
файл SceneDelegate.swift
(Создается автоматически при создании проекта, отвечает за жизненный цикл
приложения). Для этого необходимо добавить в метод scene
следующие строки.
Листинг начала метода scene
func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions)
Добавляемые строки
DSSNavigation.shared.delegate = self
DSSNavigation.shared.modalLoadingForSilentRequestType = .outer
Примечание
Параметр modalLoadingForSilentRequestType
отвечает за отображение модального окна загрузки сетевой активности SDK.
- Значение
modalLoadingForSilentRequestType = .outer
означает, что модальное окно сетевой активности SDK будет реализовано тем, кто встраивает SDK. При использовании данного типа реализации собственные окна загрузки необходимо настраивать и отображать собственными средствами в методахneedShowLoading
/needHideLoading
. - Значение
modalLoadingForSilentRequestType = .inner
означает, что модальное окно сетевой активности SDK будет отображается средствами SDK.
Пример работы с UI в SDK и реализация протокола DSSNavigationDelegate
в файле SceneDelegate.swift
,
где currentVC
- текущий UIViewController, отображаемый собственным приложением. Отображение модальных окон
сетевой загрузки не предусмотрено.
import UIKit
import DSSFramework
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var currentVC: UIViewController?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//...Собственная работа с UI
DSSNavigation.shared.delegate = self
DSSNavigation.shared.modalLoadingForSilentRequestType = .outer
}
//...Остальные методы SceneDelegate
}
extension SceneDelegate: DSSNavigationDelegate {
func needShowLoading() { }
func needHideLoading() { }
func needShow(navigationController: DSSNavigationController,
animated: Bool, completion: @escaping (() -> Void)) {
guard let window = self.window else { return }
self.currentVC = window.rootViewController
window.rootViewController = navigationController
if animated == true {
let options: UIView.AnimationOptions = .transitionCrossDissolve
UIView.transition(with: window, duration: 0.2, options: options,
animations: {}, completion: { completed in
completion()
})
} else {
completion()
}
}
func needHide(navigationController: DSSNavigationController,
animated: Bool, completion: @escaping (() -> Void)) {
guard let window = self.window else { return }
guard let currentVC = self.currentVC else { return }
window.rootViewController = currentVC
if animated == true {
let options: UIView.AnimationOptions = .transitionCrossDissolve
UIView.transition(with: window, duration: 0.2, options: options,
animations: {}, completion: { completed in
completion()
})
} else {
completion()
}
}
}