KeychainAccess для Swift: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Что такое KeychainAccess и зачем она нужна?

KeychainAccess — это легковесная, но мощная библиотека для Swift, которая предоставляет удобный и типобезопасный интерфейс для работы с Keychain Services (Связка ключей) от Apple. Keychain — это защищенное хранилище, встроенное в iOS, macOS, watchOS и tvOS, предназначенное для хранения конфиденциальных данных: паролей, ключей шифрования, токенов аутентификации, номеров кредитных карт и любой другой секретной информации.

Без библиотек работа с Keychain через нативный C-интерфейс (функции SecItemAdd, SecItemCopyMatching, SecItemUpdate, SecItemDelete) крайне громоздка, требует написания большого количества шаблонного кода и подвержена ошибкам. KeychainAccess решает эту проблему, предлагая:

  • Простой Swift-синтаксис: работа через свойства (get/set) и методы с понятными названиями.
  • Типобезопасность: данные автоматически преобразуются в String, Data или кастомные типы, реализующие Codable.
  • Гибкость: поддержка различных уровней доступа (доступность приложения, после разблокировки устройства, с биометрией), работа с группами Keychain и iCloud синхронизацией.
  • Безопасность по умолчанию: библиотека использует лучшие практики безопасности, установленные Apple.

Библиотека идеально подходит для хранения токенов OAuth, паролей пользователей, ключей API, seed-фраз криптокошельков и любых других данных, которые нельзя хранить в UserDefaults или в файловой системе в открытом виде.

Установка KeychainAccess

KeychainAccess не устанавливается через pip (Python) или npm (JavaScript). Это нативная библиотека для экосистемы Apple. Основные способы установки:

1. Swift Package Manager (SPM) — Рекомендуемый способ

В Xcode: File → Add Packages... → вставьте URL репозитория:

https://github.com/kishikawakatsumi/KeychainAccess.git

Выберите версию (обычно "Up to Next Major" с последней стабильной) и добавьте пакет в ваш target.

Или добавьте зависимость в Package.swift вашего пакета:

// swift-tools-version:5.7
import PackageDescription

let package = Package(
    name: "MyPackage",
    dependencies: [
        .package(url: "https://github.com/kishikawakatsumi/KeychainAccess.git", from: "4.2.2")
    ],
    targets: [
        .target(
            name: "MyPackage",
            dependencies: ["KeychainAccess"]),
    ]
)

2. CocoaPods

Добавьте строку в ваш Podfile:

pod 'KeychainAccess'

Затем выполните pod install.

3. Carthage

Добавьте в Cartfile:

github "kishikawakatsumi/KeychainAccess"

Затем выполните carthage update и добавьте фреймворк в ваш проект.

Быстрый старт с KeychainAccess

После установки импортируйте библиотеку: import KeychainAccess

Самый простой пример — сохранение и чтение строки:

import KeychainAccess

// Создаем экземпляр для работы с Keychain приложения
let keychain = Keychain(service: "com.example.myapp")

// Сохраняем значение
try keychain.set("my_secret_password", key: "user_password")

// Читаем значение
if let password = try keychain.get("user_password") {
    print("Найденный пароль: \(password)")
} else {
    print("Пароль не найден")
}

// Удаляем значение
try keychain.remove("user_password")

Этот код делает три основные операции: запись, чтение и удаление. Обратите внимание на обработку ошибок через try — операции с Keychain могут выбрасывать исключения (например, при проблемах с доступом или при отсутствии прав).

Основные методы и функции KeychainAccess

Рассмотрим 10 ключевых методов библиотеки. Все примеры предполагают наличие импорта import KeychainAccess.

1. init(service:accessGroup:) — Создание экземпляра

Что делает: Инициализирует объект Keychain для работы с определенным сервисом (обычно идентификатор вашего приложения или его bundle identifier). Позволяет указать группу доступа для шаринга данных между приложениями.

Параметры:

  • service: String — Имя сервиса. Рекомендуется использовать bundle identifier или уникальную строку.
  • accessGroup: String? — (Опционально) Имя группы Keychain для шаринга данных между приложениями одного разработчика.

Пример:

let keychain = Keychain(service: "com.mycompany.myapp")
let sharedKeychain = Keychain(service: "com.mycompany.shared", accessGroup: "ABCDE12345.com.mycompany.shared")

2. set(_:key:) — Сохранение строки

Что делает: Сохраняет строковое значение в Keychain по указанному ключу. Если запись с таким ключом уже существует, она будет перезаписана.

Параметры:

  • value: String? — Значение для сохранения. Если передать nil, метод поведет себя как remove.
  • key: String — Уникальный ключ для доступа к значению.

Пример:

let keychain = Keychain(service: "com.example.app")
try keychain.set("user@example.com", key: "email")
try keychain.set(nil, key: "email") // Удалит запись

3. get(_:) — Чтение строки

Что делает: Извлекает строковое значение по указанному ключу. Возвращает String? — nil, если запись не найдена.

Параметры:

  • key: String — Ключ для поиска.

Пример:

let keychain = Keychain(service: "com.example.app")
if let token = try keychain.get("auth_token") {
    print("Токен: \(token)")
} else {
    print("Токен не найден")
}

4. remove(_:) — Удаление записи

Что делает: Удаляет запись из Keychain по указанному ключу. Если запись не существует, метод не выбрасывает ошибку (является идемпотентным).

Параметры:

  • key: String — Ключ записи для удаления.

Пример:

let keychain = Keychain(service: "com.example.app")
try keychain.remove("temporary_session")
try keychain.remove("non_existent_key") // Безопасно, ошибки не будет

5. set(_:key:) — Сохранение Data (перегрузка)

Что делает: Сохраняет бинарные данные (Data) в Keychain. Полезно для хранения сериализованных объектов, изображений или ключей шифрования.

Параметры:

  • value: Data? — Данные для сохранения.
  • key: String — Ключ.

Пример:

let keychain = Keychain(service: "com.example.app")
let keyData = "my-secret-key".data(using: .utf8)!
try keychain.set(keyData, key: "encryption_key")

if let retrievedData = try keychain.getData("encryption_key") {
    print("Получено \(retrievedData.count) байт")
}

6. getData(_:) — Чтение Data

Что делает: Извлекает бинарные данные по ключу. Возвращает Data?.

Параметры:

  • key: String — Ключ.

Пример:

let keychain = Keychain(service: "com.example.app")
if let data = try keychain.getData("user_profile_image") {
    let image = UIImage(data: data)
}

7. allKeys() — Получение всех ключей

Что делает: Возвращает массив всех ключей ([String]), хранящихся в текущем сервисе Keychain. Полезно для инвентаризации или очистки.

Параметры: Нет.

Пример:

let keychain = Keychain(service: "com.example.app")
let keys = try keychain.allKeys()
print("Всего ключей: \(keys.count)")
for key in keys {
    print("Найден ключ: \(key)")
}

8. contains(_:) — Проверка существования ключа

Что делает: Проверяет, существует ли запись с указанным ключом в Keychain. Возвращает Bool.

Параметры:

  • key: String — Ключ для проверки.

Пример:

let keychain = Keychain(service: "com.example.app")
if try keychain.contains("api_key") {
    print("API ключ уже сохранен")
} else {
    print("API ключ отсутствует, требуется авторизация")
}

9. accessibility(_:) — Настройка уровня доступа

Что делает: Устанавливает политику доступности для последующих операций записи. Определяет, когда данные могут быть прочитаны (например, только когда устройство разблокировано, или после первой разблокировки).

Параметры:

  • value: Accessibility — Одно из значений перечисления: .whenUnlocked, .afterFirstUnlock, .whenPasscodeSetThisDeviceOnly и другие.

Пример:

let keychain = Keychain(service: "com.example.app")
    .accessibility(.whenUnlockedThisDeviceOnly) // Данные доступны только на этом устройстве и только когда оно разблокировано

try keychain.set("sensitive_data", key: "private_key")

10. authenticationPolicy(_:) — Настройка биометрической аутентификации

Что делает: Устанавливает политику аутентификации (Touch ID, Face ID или код-пароль) для доступа к данным. При чтении таких данных система запросит биометрию у пользователя.

Параметры:

  • policy: AuthenticationPolicy — Политика: .biometryAny (любая биометрия), .biometryCurrentSet (только текущие отпечатки/лицо), .userPresence (биометрия или код-пароль).

Пример:

let keychain = Keychain(service: "com.example.app")
    .accessibility(.whenUnlockedThisDeviceOnly)
    .authenticationPolicy(.biometryCurrentSet)

// Сохраняем данные, защищенные биометрией
try keychain.set("my_medical_record", key: "health_data")

// Чтение запросит Face ID / Touch ID
if let data = try keychain.get("health_data") {
    print("Данные получены после аутентификации: \(data)")
}

Рекомендаций