Настройка Keychain для безопасного хранения данных в iOS

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Настройка Keychain для безопасного хранения данных в iOS
Средняя
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Настройка Keychain для безопасного хранения данных в iOS

После обновления iOS приложение не находит токен авторизации — пользователь снова видит экран логина. Или хуже: токен сохранился, но доступен другому приложению того же вендора без каких-либо ограничений. Обе ситуации — следствие неправильно настроенного Keychain.

Где конкретно ломается

Самая частая ошибка — сохранять токены через UserDefaults. Данные попадают в Library/Preferences/*.plist, который входит в iCloud-бэкап и доступен через iTunes backup extraction инструментами вроде iBackup Viewer. Это не теоретическая угроза.

Вторая по частоте — использование Keychain без явного kSecAttrAccessible. По умолчанию значение kSecAttrAccessibleWhenUnlocked, что разумно, но многие проекты не задумываются, нужен ли доступ к данным при заблокированном экране (для background tasks) или только когда устройство разблокировано и только после первого unlock после перезагрузки. Это принципиально разные threat models.

Третья — отсутствие kSecAttrAccessGroup при работе в App Group. Если у вас основное приложение и виджет или extension, и токен не расшарен явно, extension не видит Keychain-запись, хотя Bundle ID из той же группы.

Правильная настройка через Security framework

Базовый паттерн записи:

let query: [String: Any] = [
    kSecClass as String:            kSecClassGenericPassword,
    kSecAttrService as String:      "com.example.app.auth",
    kSecAttrAccount as String:      "access_token",
    kSecAttrAccessible as String:   kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly,
    kSecValueData as String:        tokenData,
    kSecAttrAccessGroup as String:  "TEAMID.com.example.shared"  // если нужен App Group
]

kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly — правильный выбор для большинства токенов: доступен после первого разблока после перезагрузки, не синхронизируется в iCloud, не переносится на другое устройство. Если вам нужна синхронизация между устройствами пользователя (например, пароль от заметок) — тогда kSecAttrAccessibleWhenUnlocked с kSecAttrSynchronizable: kCFBooleanTrue. Но для auth-токенов синхронизация через iCloud Keychain нежелательна — компрометация одного устройства компрометирует все.

Для чтения с обновлением (upsert) — сначала SecItemUpdate, при ошибке errSecItemNotFoundSecItemAdd. Не делайте SecItemDelete + SecItemAdd — это создаёт race condition в многопоточной среде.

Biometric protection через LocalAuthentication

Если нужна биометрия перед доступом к данным (ключи шифрования, приватные ключи):

let access = SecAccessControlCreateWithFlags(
    nil,
    kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
    .biometryCurrentSet,  // .userPresence если нужен fallback на пасскод
    nil
)!

Флаг .biometryCurrentSet инвалидирует запись при изменении биометрии (новый отпечаток, переход на Face ID) — это намеренное поведение для высокосекретных данных. Для менее критичных .biometryAny сохраняет доступ после добавления новых отпечатков.

Обёртка и тестируемость

Прямые вызовы SecItemAdd в продакшн-коде делают юнит-тесты невозможными без реального Keychain. Оборачиваем в протокол:

protocol KeychainService {
    func save(_ data: Data, for key: String) throws
    func load(for key: String) throws -> Data
    func delete(for key: String) throws
}

В тестах подставляем InMemoryKeychainService. В проде — реализация через Security framework. Это стандартный подход в Clean Architecture для iOS.

Процесс работы

Аудит текущего кода — ищем UserDefaults, NSKeyedArchiver, плейн-текст в файлах. Далее проектируем KeychainService под конкретный набор хранимых данных, реализуем с правильными kSecAttrAccessible, настраиваем App Group если нужно расшаривание с extensions, покрываем unit-тестами через мок. Отдельно — проверка поведения при смене биометрии и при обновлении приложения.

Сроки — 1–3 дня. Простая замена UserDefaults на Keychain для одного типа данных — ближе к дню. Полный аудит + рефакторинг + App Group + биометрия — до трёх.