Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. iOS SDK
Code

Защита данных iOS в Rest: Keychain

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Securing iOS Data at Rest.
Securing iOS Data at Rest: Protecting the User's Data
Securing iOS Data at Rest: Encryption

Russian (Pусский) translation by Ilya Nikov (you can also view the original English article)

Любое приложение, которое сохраняет данные пользователя, должно заботиться о безопасности и конфиденциальности этих данных. Как мы видели с недавними нарушениями данных, могут быть очень серьезные последствия для отказа от защиты хранимых данных ваших пользователей. В этом уроке вы узнаете некоторые рекомендации по защите данных своих пользователей.

В предыдущей статье вы узнали, как защитить файлы с помощью API защиты данных. Файловая защита - это мощная функция для безопасного хранения объемных данных. Но это так же может быть излишним для небольшого количества информации, такой как например ключ или пароль. Рекомендованное решение для этих типов элементов - это ключевое слово.

Сервисы Keychain

Keychain - отличное место для хранения небольших объемов информации, таких как конфиденциальные строки и идентификаторы, которые сохраняются даже тогда, когда пользователь удаляет приложение. Примером может быть токен устройства или сеанса, который ваш сервер возвращает в приложение при регистрации. Если вы называете это секретной строкой или уникальным токеном, связка ключей относится ко всем этим элементам как к паролям.

Есть несколько популярных сторонних библиотек для сервисов keychain, таких как Strongbox (Swift) и SSKeychain (Objective-C). Или, если вы хотите полностью контролировать свой собственный код, вы можете напрямую использовать API-интерфейс Keychain, который является C API.

Я кратко объясню, как работает Keychain. Можете рассматривать Keychain как типичную базу данных, где вы делаете запросы к таблице. Для функций API-интерфейса Keychain требуется объект CFDictionary, содержащий атрибуты запроса.

Каждая запись в цепочке ключей содержит имя службы. Имя службы - это идентификатор: ключ для любого значения, которое вы хотите сохранить или получить в цепочке ключей. Чтобы объект связки ключей сохранялся только для определенного пользователя, вы также можете указать имя учетной записи.

Поскольку каждая функция keychain принимает аналогичный словарь со многими из тех же параметров, что и запрос, вы можете избежать дублирования кода, создав вспомогательную функцию, которая возвращает этот словарь.

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

Аналогично тому, как вы можете установить уровень защиты для отдельных файлов (как мы обсуждали в предыдущей статье), вы также можете установить уровни защиты для вашего объекта keychain с помощью ключа kSecAttrAccessible.

Добавление пароля

Функция SecItemAdd() добавляет данные в цепочку ключей. Эта функция принимает объект Data, что делает ее универсальным для хранения многих объектов. Используя функцию запроса пароля, которую мы создали выше, давайте сохраним строку в связке ключей. Для этого нам просто нужно преобразовать String в Data.

Удаление пароля

Чтобы предотвратить дублирование вставок, код выше сначала удаляет предыдущую запись, если она есть. Теперь напишем эту функцию. Это выполняется с помощью функции SecItemDelete().

Получение пароля

Затем, чтобы получить запись из связки ключей, используйте функцию SecItemCopyMatching(). Она вернет AnyObject, соответствующий вашему запросу.

В этом коде мы устанавливаем параметр kSecReturnData в kCFBooleanTrue. KSecReturnData означает, что фактические данные будут возвращены. Другой вариант - вернуть атрибуты (kSecReturnAttributes) элемента. Ключ принимает тип CFBoolean, который содержит константы kCFBooleanTrue или kCFBooleanFalse. Мы устанавливаем kSecMatchLimit в kSecMatchLimitOne, чтобы возвращался только первый элемент в цепочке ключей, а не неограниченное количество результатов.

Открытые и закрытые ключи

Связка ключей также является рекомендуемым местом для хранения объектов открытого и закрытого ключа, например, если ваше приложение работает и должно хранить объекты EC или RSA SecKey.

Основное различие заключается в том, что вместо того, чтобы сообщать связке ключей о сохранении пароля, мы можем сказать, что она хранит ключ. Фактически, мы можем получить конкретную информацию, задав типы хранимых ключей, например, публичные или частные. Все, что нужно сделать, - это адаптировать вспомогательную функцию запроса для работы с типом ключа, который вам нужен.

Ключи обычно идентифицируются с использованием тега обратного домена, такого как com.mydomain.mykey, а не именем службы и учетной записи (поскольку открытые ключи открываются совместно между различными компаниями или сущностями). Мы возьмем строки службы и аккаунт и преобразуем их в объект Data. Например, приведенный выше код, адаптированный для хранения RSA Private SecKey, будет выглядеть следующим образом:

Пароли приложений

Элементы, защищенные флагом kSecAttrAccessibleWhenUnlocked, разблокируются только тогда, когда устройство будет разблокировано, но это еще и зависит от пользователя, у которого есть код доступа или сенсорный идентификатор, созданный в первую очередь.

Учетные данные applicationPassword позволяют связать элементы в связке ключей с помощью дополнительного пароля. Таким образом, если у пользователя нет кода доступа или сенсорного идентификатора, элементы будут по-прежнему безопасными и добавят дополнительный уровень безопасности, если у них есть набор паролей.

В качестве примера сценария, после того как ваше приложение будет аутентифицироваться на вашем сервере, ваш сервер может вернуть пароль через HTTPS, который требуется для разблокирования элемента keychain. Это предпочтительный способ предоставления дополнительного пароля. Жестко прописывать пароль в двоичном формате не рекомендуется.

Другим сценарием может быть получение дополнительного пароля с предоставленного пользователем пароля в вашем приложении; Однако для этого требуется больше работы (с использованием PBKDF2). В следующем учебнике мы рассмотрим безопасность паролей пользователей.

Другое использование пароля приложения - это хранение чувствительного ключа, например, который вы бы не хотели показывать только потому, что пользователь еще не установил пароль.

applicationPassword доступно только для iOS 9 и выше, поэтому вам понадобится резерв, который не будет использовать applicationPassword, если вы нацеливаетесь на более низкие версии iOS. Чтобы использовать код, вам нужно добавить следующее в заголовок:

Следующий код устанавливает пароль для запроса Dictionary.

Обратите внимание, что мы устанавливаем kSecAttrAccessControl в Dictionary. Это используется вместо kSecAttrAccessible, который ранее был установлен в нашем методе passwordQuery. Если вы попытаетесь использовать оба варианта, вы получите ошибку OSStatus -50.

Аутентификация пользователя

Начиная с iOS 8, вы можете хранить данные в связке ключей, доступ к которой возможен только после успешной аутентификации пользователя на устройстве с помощью Touch ID или кода доступа. Когда нужно аутентифицировать пользователя, Touch ID получит приоритет, если он настроен, в противном случае будет показан экран кода доступа. Сохранение в связке ключей не потребует аутентификации пользователя, а получение данных потребует.

Вы можете установить элемент keychain, требующий аутентификации пользователя, предоставив объект управления доступом, установленный на .userPresence. Если код доступа не установлен, любые запросы к связке ключей с .userPresence не будут выполнены.

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

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

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

При извлечении данных с помощью SecItemCopyMatching() функция покажет интерфейс аутентификации и дождется, пока пользователь будет использовать Touch ID или введет пароль. Поскольку SecItemCopyMatching () будет блокироваться до тех пор, пока пользователь не завершит проверку подлинности, вам нужно будет вызвать функцию из фонового потока, чтобы позволить основному потоку пользовательского интерфейса оставаться отзывчивым.

Опять же, мы устанавливаем kSecAttrAccessControl в запросе Dictionary. Вам нужно будет удалить kSecAttrAccessible, который ранее был установлен в нашем методе passwordQuery. Использование обоих сразу приведет к ошибке OSStatus -50.

Заключение

В этой статье вы ознакомились с API-интерфейсом Keychain. Наряду с API защиты данных, который мы видели в предыдущей статье, использование этой библиотеки является частью лучших практик по обеспечению безопасности данных.

Однако, если у пользователя нет кода доступа или сенсорного идентификатора на устройстве, шифрование на одном из фреймворков не сработает. Поскольку API-интерфейсы Keychain и Data Protection обычно используются приложениями iOS, они иногда становятся целью злоумышленников, особенно на взломанных устройствах. Если ваше приложение не работает с высокочувствительной информацией, это может быть приемлемым риском. В то время как iOS постоянно обновляет безопасность фреймворков, мы по-прежнему находимся во власти пользователя, обновляющего ОС, используя стойкий пароль доступа, а не джейлбрейк своего устройства.

Связка ключей предназначена для небольших фрагментов данных, и у вас может быть больше данных для защиты, которые не зависят от аутентификации устройства. В то время как обновления iOS добавляют некоторые замечательные новые функции, такие как пароль приложения, вам все равно придется поддерживать более низкие версии iOS и по-прежнему иметь сильную безопасность. По некоторым из этих соображений вы можете вместо этого сами зашифровать данные.

Последняя статья в этой серии описывает шифрование данных с использованием AES-шифрования, и, хотя это более продвинутый подход, он позволяет вам полностью контролировать, как и когда ваши данные зашифровываются.

Так что следите за обновлениями. И тем временем, ознакомьтесь с некоторыми из наших других статей о разработке приложений для iOS!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.