Как и где безопасно хранить секретные изображения (или другие бинарные данные) в iOS-приложении?

Ответ

Для хранения конфиденциальных данных, таких как изображения, необходимо использовать защищенные API iOS. Никогда не храните секреты в UserDefaults, plist-файлах или в открытом виде в директориях Documents или Caches.

Рекомендуемые подходы:

  1. Keychain Services: Лучший выбор для небольших данных (практический лимит ~4KB). Данные шифруются аппаратным ключом и защищены на уровне системы.

    // Сохранение данных изображения в Keychain
    let imageData = UIImage(named: "secret")!.pngData()!
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: "com.yourapp.secretImage",
        kSecValueData as String: imageData,
        kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly // Строгий атрибут доступа
    ]
    SecItemAdd(query as CFDictionary, nil)
  2. Шифрование + Файловая система: Для больших файлов. Зашифруйте данные с помощью CryptoKit перед записью в защищенную директорию.

    import CryptoKit
    // Генерация/хранение ключа — в Keychain!
    let key = SymmetricKey(size: .bits256)
    let imageData = try Data(contentsOf: imageURL)
    let sealedBox = try AES.GCM.seal(imageData, using: key)
    try sealedBox.combined?.write(to: encryptedFileURL)
  3. Secure Enclave: Максимальный уровень защиты для криптографических ключей (например, ключа для расшифровки файла). Доступно только на устройствах с FaceID/TouchID. Используется для операций с ключами, но не для хранения самих изображений.

Атрибуты доступа Keychain (kSecAttrAccessible): Используйте kSecAttrAccessibleWhenUnlockedThisDeviceOnly, чтобы данные были доступны только после разблокировки устройства и не копировались в резервные копии iCloud.

Ответ 18+ 🔞

Ну слушай, история такая: если у тебя в приложении есть какие-то конфиденциальные картинки, типа паспорта или там фоток с последней пьянки, которые не должны светиться, — ты их нихуя не должен пихать куда попало.

Вот смотри, какие есть варианты, чтобы не прослыть полным распиздяем:

1. Ключница (Keychain Services) Это как сейф для мелких штук. Идеально, если твои данные влезают в ~4 килобайта. Всё шифруется на аппаратном уровне, система сама охраняет. Главное — правильно дверцу закрыть.

// Сохранение данных изображения в Keychain
let imageData = UIImage(named: "secret")!.pngData()!
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "com.yourapp.secretImage",
    kSecValueData as String: imageData,
    kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly // Вот эта штука — чтобы только на разблокированном устройстве и никуда в iCloud!
]
SecItemAdd(query as CFDictionary, nil)

Видишь этот kSecAttrAccessibleWhenUnlockedThisDeviceOnly? Это чтобы твои секреты не утекали в бэкапы и требовали разблокировки телефона. Без этого — вообще никуда.

2. Шифрование + файловая система А если картинка здоровенная, как твоё ЧСВ? Тогда сначала её надо превратить в тарабарщину с помощью CryptoKit, а потом уже куда-то складывать. Но ключ от этой тарабарщины — опять же в Ключницу, ёпта!

import CryptoKit
// Генерация/хранение ключа — в Keychain, блядь!
let key = SymmetricKey(size: .bits256)
let imageData = try Data(contentsOf: imageURL)
let sealedBox = try AES.GCM.seal(imageData, using: key)
try sealedBox.combined?.write(to: encryptedFileURL)

Получился файл, который выглядит как белиберда. Без ключа — нихуя не прочитать. Красота.

3. Secure Enclave Это уже для параноиков высшей лиги. Такая отдельная чёрная коробочка в процессоре, куда можно положить криптографический ключ (саму фотку — нет, она не влезет). Используется в связке с FaceID/TouchID. Если телефон вскроют и достанут чип — ключа там уже не будет. Вообще. Пиздец как надёжно.

Итог, чувак: Запомни раз и навсегда — UserDefaults, plist-файлы или просто скидывание файлов в Documents для секретных данных — это уровень "я мудак". Это как оставить ключи от квартиры под ковриком, на котором написано "КЛЮЧИ ЗДЕСЬ". Всё, что хоть немного конфиденциально — либо в Keychain с правильными атрибутами, либо зашифровано так, чтобы у охуевшего соседа глаза на лоб полезли. Выбирай.