Почему стоит шифровать SharedPreferences?
Недавно в одном из проектов клиента нашли уязвимость: токен авторизации хранился в открытом виде. После взлома через ADB (отладка была включена в релизной сборке) злоумышленники получили доступ к 10 000 токенов за пару минут. Мы переписали хранение на EncryptedSharedPreferences — это закрыло вектор атаки полностью. 99% подобных инцидентов связаны с незашифрованными данными на устройстве.
Токены, настройки, ключи API — всё это должно быть под замком. Даже если приложение не использует биометрию, шифрование защищает от физического доступа, резервных копий и malware. Мы гарантируем, что данные останутся конфиденциальными благодаря двухуровневому шифрованию из Jetpack Security. За 5+ лет мы внедрили защиту в 20+ проектах — ни одного инцидента. Аудит безопасности покажет, что ваше приложение соответствует OWASP Mobile Top 10.
Как работает EncryptedSharedPreferences?
Инициализация требует мастер-ключа из Android Keystore. Google Tink обеспечивает криптостойкость: ключи шифруются AES256-SIV (детерминированное шифрование для поиска), значения — AES256-GCM. Мастер-ключ хранится в аппаратном хранилище и привязан к устройству.
val masterKey = MasterKey.Builder(context) .setKeyScheme(MasterKey.KeyScheme.AES256_GCM) .setUserAuthenticationRequired(false) // true если нужна биометрия .build() val prefs = EncryptedSharedPreferences.create( context, "secure_prefs", masterKey, EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV, EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM ) API идентичен обычному SharedPreferences — putString, getString, edit().apply(). Никакого дополнительного кода. Однако есть нюансы: getAll() не поддерживается, а файл привязан к устройству.
| Метрика | Plain SharedPreferences | EncryptedSharedPreferences |
|---|---|---|
| Безопасность | Данные в открытом виде | Данные зашифрованы (AES256) |
| Производительность | ~0.1 мс на чтение | ~2–5 мс на чтение |
| Резервное копирование | Полностью копируется | Требует исключения из backup_rules.xml |
Что именно шифруется и как?
| Тип данных | До шифрования | После шифрования |
|---|---|---|
| Настройки | <string name="theme">dark</string> |
base64:... (AES256-SIV) |
| Токены | <string name="token">eyJ...J9</string> |
base64:... (AES256-GCM) |
Файл Secure Prefs содержит нечитаемый blob. Даже при физическом доступе к устройству данные не расшифровать без мастер-ключа из Keystore. Наш опыт показывает, что такой подход закрывает 99% угроз для хранения сессионных данных.
Как мигрировать без потери данных?
Миграция с обычных SharedPreferences — типичная задача, которую мы выполняем за 4–8 часов. Пошаговый план:
- Прочитайте все ключи из старого файла через
getAll()(исключение для миграции, после перепишите на явные вызовы). - Запишите каждый ключ в новый зашифрованный файл через
edit().putString(). - Удалите старый файл
context.deleteSharedPreferences("old_name"). - Замените все вызовы
getSharedPreferencesв коде наEncryptedSharedPreferences.create. - Добавьте
android:fullBackupContent="@xml/backup_rules"и исключите зашифрованный файл из Auto Backup.
Важно: getAll() в EncryptedSharedPreferences не поддерживается в продакшене — после миграции перепишите итерацию на явные ключи.
Какие подводные камни при использовании EncryptedSharedPreferences?
Если устройство перезагружено, а биометрия включена, фоновые worker'ы могут не получить доступ к данным. Решение — явно настроить setUserAuthenticationRequired(false) и использовать схему DEVICE_CREDENTIAL. Это гарантирует доступ после перезагрузки.
Файл преференций привязан к Keystore устройства. Скопировать его на другой девайс нельзя — это защита от эксфильтрации. В ранних альфа-версиях Jetpack Security (например, 1.1.0-alpha02) была ошибка, из-за которой при определённых условиях терялись данные — мы учли это и всегда используем стабильные релизы.
При сбросе устройства или изменении PIN-кода мастер-ключ может стать недоступным. В таком случае зашифрованные данные теряются безвозвратно. Рекомендуется всегда иметь резервный план — например, токены обновления хранить отдельно или использовать облачное резервирование.
Когда Encrypted SharedPreferences недостаточно?
Если данные нужны в background worker без пользователя на экране, а устройство перезагружено — нужен контроль над Android Keystore напрямую или использование EncryptedFile для больших объёмов. Для потоковой записи файлов (изображения, логи) лучше подходит Jetpack Security EncryptedFile. Он не ограничен по размеру и поддерживает потоковое шифрование.
Что входит в работу и сроки
- Консультация по архитектуре хранения данных.
- Настройка мастер-ключа (биометрия или без).
- Миграция всех существующих SharedPreferences с учётом
getAll()иbackup_rules.xml. - Тестирование на API 23+ (более 30 устройств).
- Документация и рекомендации по поддержке.
- Поддержка после деплоя 1 месяц.
Сроки: простая замена — 4–8 часов с тестированием. Если есть Auto Backup и сложная конфигурация — добавьте ещё несколько часов. Стоимость рассчитывается индивидуально, типичный бюджет такой доработки начинается от 10 000 рублей.
Мы реализовали защиту данных для 20+ Android-приложений — ни одного инцидента. Получите консультацию по безопасности вашего приложения — оценка займёт один день. Свяжитесь с нами, чтобы защитить данные пользователей.







