EncryptedSharedPreferences: що це таке, API та як використовувати

Автор: IT Sectr Опубліковано: 2026-03-14 Час читання: 10 хв

EncryptedSharedPreferences — це компонент бібліотеки AndroidX Security, що забезпечує прозоре шифрування даних, які зберігаються через API SharedPreferences. На відміну від звичайних SharedPreferences, де дані зберігаються у відкритому XML-файлі, EncryptedSharedPreferences автоматично шифрує ключі та значення перед записом на диск. Згідно з Android Developers, бібліотека використовує AES-256 GCM для значень і AES-256 SIV (RFC 5297) для ключів, забезпечуючи конфіденційність та цілісність даних.

Головне

  • EncryptedSharedPreferences — обгортка над SharedPreferences з автоматичним шифруванням усіх збережених даних
  • Шифрування використовує AES-256 GCM для значень і AES-256 SIV для ключів через Android Keystore
  • Authenticated Encryption (AEAD) гарантує, що дані не були змінені після запису
  • Master Key зберігається в Android Keystore і захищена апаратно на пристроях з TEE
  • API повністю сумісний з SharedPreferences — заміна відбувається без зміни коду читання та запису

Що таке EncryptedSharedPreferences?

EncryptedSharedPreferences — це клас із пакета androidx.security.crypto, представлений в AndroidX Security 1.0.0 (2019). Він реалізує інтерфейс SharedPreferences, але всі операції запису (putString, putInt, putBoolean тощо) попередньо шифрують дані, а операції читання розшифровують їх перед поверненням.

Проблема звичайних SharedPreferences

Стандартні SharedPreferences зберігають дані у файл XML у каталозі додатка (/data/data/package/shared_prefs/). Файл не зашифрований — при root-доступі до пристрою або під час аналізу резервної копії всі дані читаються як звичайний XML. Токени автентифікації, ключі API, персональні дані користувача стають доступними зловмиснику.

EncryptedSharedPreferences вирішує цю проблему на рівні бібліотеки: дані шифруються перед записом на диск і розшифровуються під час читання. Розробнику не потрібно викликати криптографічні функції вручну — API залишається ідентичним звичайним SharedPreferences.

Історія та версії

Бібліотека AndroidX Security v1.0.0 вийшла в грудні 2019 року. EncryptedSharedPreferences замінила застарілий підхід із ручним шифруванням через Cipher + SharedPreferences. Поточна стабільна версія — 1.1.0-alpha06 (2024), що підтримує API 19+. Бібліотека входить до складу Jetpack і не потребує додаткових дозволів.

За даними Google Security Blog (2024), EncryptedSharedPreferences — рекомендований спосіб зберігання конфіденційних налаштувань додатка, які не потребують синхронізації через хмару. Для більш складних сценаріїв пропонується Room із шифруванням через SQLCipher.

Як працює EncryptedSharedPreferences?

EncryptedSharedPreferences використовує дворівневу схему шифрування: мастер-ключ (Master Key) зберігається в Android Keystore, а для шифрування даних використовуються похідні ключі. Це поєднує захист Keystore і продуктивність симетричного шифрування.

Схема шифрування: AES-256 GCM + SIV

Для значень використовується AES-256 GCM (Galois/Counter Mode) — режим автентифікованого шифрування (AEAD), що забезпечує конфіденційність та цілісність даних. Для ключів (імен параметрів) застосовується AES-256 SIV (RFC 5297) — детерміноване шифрування, необхідне для пошуку за ключем без розкриття його вмісту.

Кожен файл EncryptedSharedPreferences містить зашифровані пари ключ-значення. Структура файлу: спочатку заголовок із метаданими (версія, ідентифікатор ключа), потім список зашифрованих записів. Файл не є валідним XML і не читається текстовими редакторами.

MasterKey і KeyStore

Клас MasterKey відповідає за створення та керування 256-бітним мастер-ключем, який зберігається в Android Keystore. MasterKey.Builder дозволяє налаштувати: тип сховища (Keystore або програмний), захист біометрією, час життя ключа. За замовчуванням мастер-ключ генерується в Android Keystore з алгоритмом AES/GCM/NoPadding.

kotlin
import androidx.security.crypto.MasterKey
import androidx.security.crypto.EncryptedSharedPreferences

fun getEncryptedPrefs() {
    val masterKey = MasterKey.Builder(context)
        .setKeyScheme(MasterKey.AES256_GCM_SPEC)
        .build()

    val prefs = EncryptedSharedPreferences.create(
        context,
        "secure_prefs",
        masterKey,
        EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
        EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
    )
}

Налаштування та конфігурація шифрування

EncryptedSharedPreferences.create приймає п'ять параметрів: контекст, ім'я файлу, мастер-ключ, схему шифрування ключів та схему шифрування значень. Від вибору схем залежить продуктивність та рівень захисту.

Схеми шифрування ключів

AES256_SIV — детерміноване шифрування: однакові ключі завжди дають однаковий зашифрований текст. Це необхідно для пошуку за ключем (SharedPreferences.getX(key)). Недолік: зловмисник може визначити, які ключі використовуються, за повторюваними шифротекстами. AES256_SIV2 — покращена версія з додатковою рандомізацією.

Для значень використовується AES256_GCM. GCM додає 12-байтовий IV (вектор ініціалізації) та 16-байтовий тег автентифікації до кожного значення. Це забезпечує конфіденційність (ніхто не прочитає значення) та автентифікацію (ніхто не підмінить значення без виявлення).

Біометричний захист мастер-ключа

Метод setUserAuthenticationRequired(true) у MasterKey.Builder вимагає біометричного підтвердження перед отриманням мастер-ключа з Keystore. Це додає додатковий рівень: навіть якщо додаток запущено на розблокованому пристрої, зловмисник не зможе прочитати EncryptedSharedPreferences без Face ID або Touch ID.

Важливо: при setUserAuthenticationRequired мастер-ключ стає недоступним, якщо користувач змінив або видалив біометрію. Необхідно обробляти KeyPermanentlyInvalidatedException та створювати новий мастер-ключ з міграцією даних.

kotlin
fun createBiometricKey(): MasterKey {
    return MasterKey.Builder(context)
        .setKeyScheme(MasterKey.AES256_GCM_SPEC)
        .setUserAuthenticationRequired(true)
        .setRequestStrongBoxBacked(true)
        .build()
}

fun writeSecureToken(token: String) {
    try {
        prefs.edit().putString("auth_token", token).apply()
    } catch (e: KeyPermanentlyInvalidatedException) {
        // Біометрія змінилася — потрібно перестворити ключ
    }
}

Приклад використання на Kotlin

Розглянемо повний приклад інтеграції EncryptedSharedPreferences в Android-додатку на Kotlin. Бібліотека androidx.security:security-crypto підключається через Gradle.

Підключення залежності

У файл build.gradle (app) додайте: implementation «androidx.security:security-crypto:1.1.0-alpha06». Для Kotlin-проектів додатково потрібен kotlin-stdlib. Ініціалізація MasterKey відбувається одноразово, зазвичай в Application.onCreate або через DI-контейнер.

Читання та запис даних

Після створення екземпляра EncryptedSharedPreferences API не відрізняється від звичайних SharedPreferences. edit() повертає Editor, усі методи (putString, getString, putBoolean, getBoolean) працюють аналогічно. Різниця лише всередині: дані шифруються при записі та розшифровуються при читанні.

kotlin
class AuthRepository(context: Context) {
    private val prefs = createEncryptedPrefs(context)

    fun saveCredentials(login: String, password: String) {
        prefs.edit()
            .putString("login", login)
            .putString("password", password)
            .apply()
    }

    fun getToken(): String? {
        return prefs.getString("auth_token", null)
    }

    fun clearAll() {
        prefs.edit().clear().apply()
    }
}

Міграція зі звичайних SharedPreferences

Для міграції існуючих даних із незахищених SharedPreferences в EncryptedSharedPreferences необхідно: прочитати всі дані зі старого файлу, створити новий EncryptedSharedPreferences, записати всі дані, видалити старий файл. Google не надає вбудованого мігратора — розробник реалізує його самостійно.

Порівняння зі звичайними SharedPreferences

Вибір між SharedPreferences та EncryptedSharedPreferences залежить від типу даних, що зберігаються. Для налаштувань інтерфейсу (тема, мова, сортування) звичайні SharedPreferences достатні. Для конфіденційної інформації (токени, паролі, ключі) EncryptedSharedPreferences обов'язковий.

Продуктивність

EncryptedSharedPreferences повільніший за звичайні через криптографічні операції. Запис одного рядкового значення займає ~5-15 мс (залежить від розміру даних та апаратного прискорення AES). Читання — 2-5 мс. Для більшості додатків це непомітно, але при пакетних операціях (міграція, відновлення) варто використовувати apply() замість commit().

Безпека

Звичайні SharedPreferences не забезпечують жодного криптографічного захисту: файл XML читається будь-яким процесом із root-доступом або через adb backup. EncryptedSharedPreferences шифрує дані на рівні додатка, а мастер-ключ зберігається в Android Keystore з можливістю апаратного захисту (StrongBox).

ХарактеристикаSharedPreferencesEncryptedSharedPreferences
ЗберіганняВідкритий XMLЗашифрований бінарний файл
ШифруванняНемаєAES-256 GCM + SIV
Захист ключівНемаєAndroid Keystore + StrongBox
Продуктивність0.1-1 мс2-15 мс
РекомендаціяНалаштування UIТокени, ключі, PII

Коли вибирати EncryptedSharedPreferences

Використовуйте EncryptedSharedPreferences для зберігання: refresh token OAuth, ключів API для зовнішніх сервісів, email або номера телефону користувача, конфіденційних налаштувань додатка (PIN, прапорці автентифікації). Для зберігання біометричних даних або великих документів EncryptedSharedPreferences не підходить — використовуйте EncryptedFile або Room із SQLCipher.

Загальне правило: якщо дані при витоку завдадуть шкоди користувачеві або бізнесу — використовуйте EncryptedSharedPreferences. Якщо дані лише косметичні (тема, мова, сортування) — звичайні SharedPreferences. EncryptedSharedPreferences має сенс впроваджувати одразу, без рефакторингу: заміна в існуючому проекті потребуватиме міграції та обробки старих незашифрованих даних.

Пам'ятайте, що EncryptedSharedPreferences не захищає дані під час роботи додатка — тільки на диску. Якщо зловмисник має доступ до пам'яті процесу, розшифровані дані можуть бути перехоплені. Використовуйте додатковий захист: ProGuard/DexGuard для обфускації.

Часті запитання

Чим EncryptedSharedPreferences відрізняється від DataStore?

Jetpack DataStore — це більш сучасна альтернатива SharedPreferences, заснована на Flow та Kotlin корутинах. DataStore не шифрує дані за замовчуванням, але може бути скомбінований з EncryptedSharedPreferences або використовуватися з ручним шифруванням через Proto DataStore з криптографічними протоколами.

Чи можна використовувати EncryptedSharedPreferences для великих обсягів даних?

Не рекомендується. EncryptedSharedPreferences призначений для невеликих обсягів (до 100-200 КБ). Для великих даних використовуйте Room із SQLCipher або шифрування файлів через EncryptedFile із тієї ж бібліотеки AndroidX Security.

Чи підтримує EncryptedSharedPreferences міграцію при оновленні схеми?

Ні, автоматичної міграції схеми немає. При зміні структури даних розробник повинен вручну прочитати старі дані через старий KeyGen та записати їх через новий. Рекомендується зберігати версію схеми в окремому параметрі.

Який мінімальний API рівень потрібен?

AndroidX Security 1.0.0 підтримує API 19+ (Android KitKat). Версія 1.1.0-alpha06 також підтримує API 19+. Для роботи StrongBox потрібен API 28+ та пристрій з апаратною підтримкою (Google Pixel 3+, Samsung Galaxy S9+).

Чи безпечно зберігати refresh token в EncryptedSharedPreferences?

Так, refresh token — один з основних сценаріїв використання. Шифрування AES-256 GCM, мастер-ключ в Keystore, біометричний захист — достатній рівень для OAuth токенів. Для access token з коротким часом життя також підходить, хоча деякі команди віддають перевагу зберіганню його в пам'яті.

Підсумки

  • EncryptedSharedPreferences — обгортка SharedPreferences з автоматичним шифруванням через AES-256 GCM (значення) та SIV (ключі)
  • Master Key створюється через MasterKey.Builder і зберігається в Android Keystore з опціями біометрії та StrongBox
  • API повністю сумісний: edit, putString, getString, apply, clear — все як у звичайних SharedPreferences
  • Продуктивність: 2-15 мс на операцію, що непомітно для користувача при стандартних сценаріях
  • Безпека: автентифіковане шифрування (AEAD) запобігає як читанню, так і підміні даних
  • Міграція зі звичайних SharedPreferences потребує ручного перенесення даних через старий та новий файли
  • Використовуйте EncryptedSharedPreferences для токенів, ключів API, паролів та інших конфіденційних налаштувань

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також