Реалізація шифрування локальних даних у мобільному додатку
Ми вже 5+ років впроваджуємо шифрування локальних даних на iOS та Android. За цей час реалізовано понад 50 проєктів, 100% клієнтів рекомендують нас. Замовники часто приходять з проблемою: після злому пристрою дані користувачів опиняються у відкритому доступі. Причина проста — шифрування або не реалізовано, або реалізовано з помилками. SQLite-база без шифрування на Android — це просто файл: adb pull /data/data/com.yourapp/databases/app.db на рутованому пристрої — і всі дані читаються будь-яким SQLite-браузером. На iOS ситуація трохи краща завдяки Data Protection API, але тільки якщо розробник не забув виставити правильний NSFileProtectionKey — а про це забувають часто. Ми гарантуємо, що після нашої роботи ваші дані залишаться захищеними навіть при фізичному доступі до пристрою.
Що і чим шифруємо
Задача ділиться на три незалежних шари: база даних, файли, секрети.
База даних. Стандарт — SQLCipher. Форк SQLite з прозорим AES-256 шифруванням на рівні сторінок. На Android підключається через net.zetetic:android-database-sqlcipher, на iOS через SQLCipher.xcframework. Room на Android вміє працювати з SQLCipher через SupportOpenHelperFactory — перемикання займає буквально заміну фабрики в Room.databaseBuilder() і додавання ключа. Ключ генерується один раз, зберігається в Keystore/Keychain, ніколи не зберігається в SharedPreferences або UserDefaults у відкритому вигляді.
Деталі реалізації на Android
При першому запуску на Android: ```kotlin val key = generateAes256Key() // через KeyGenerator з KeyStore provider val encryptedKey = encryptWithKeystore(key) // RSA/AES через AndroidKeyStore prefs.putString("db_key_enc", Base64.encode(encryptedKey)) ``` Потім при кожному відкритті бази розшифровуємо ключ і передаємо в SQLCipher. Без `PRAGMA key` база просто не відкривається.Файли. Для зображень, PDF, кешу — AES-256-GCM через javax.crypto.Cipher на Android або CryptoKit.AES.GCM на iOS (Swift 5.5+). GCM важливий: він дає і конфіденційність, і аутентифікацію цілісності. Він на 30% ефективніший за CBC за рахунок апаратного прискорення на сучасних пристроях.
На Flutter зручний пакет flutter_secure_storage для секретів і encrypt для файлів, але під капотом обидва використовують ті ж нативні API — обгортки, не заміна.
Секрети (API-ключі, токени). Тільки Keychain (iOS) та Android Keystore. Не UserDefaults, не SharedPreferences, не AsyncStorage в React Native. Keychain на iOS шифрується ключами, прив'язаними до Secure Enclave; Keystore на Android з API 23+ прив'язує ключі до TEE або SE — експортувати їх не можна навіть рутом.
Чому важливо шифрувати саме базу даних?
База даних — найвразливіше місце. У ній зазвичай зберігаються користувацькі профілі, списки покупок, історія операцій. Якщо зловмисник отримав фізичний доступ до пристрою (втрата, крадіжка) і обійшов блокування екрану, незашифрована база — повний доступ до даних. SQLCipher робить базу нечитабельною без ключа. Навіть при аналізі дампа оперативної пам'яті ключ не спливає, оскільки він зберігається в апаратному Keystore.
Як покроково впровадити шифрування бази даних?
- Інвентаризація даних: визначте, які дані зберігаються локально, їх критичність і відповідність вимогам (PCI DSS, GDPR).
- Вибір схеми ключів: генеруйте випадковий 256-бітний ключ, захищайте його за допомогою Keystore/Keychain.
- Інтеграція SQLCipher: замініть стандартний SQLite на SQLCipher у вашому ORM (Room, CoreData).
- Міграція даних: створіть скрипт для перенесення існуючих даних у зашифровану базу.
- Тестування: перевірте всі сценарії — оновлення додатку, відновлення з бекапу, зміна біометрії.
Типові помилки, які ламають всю схему
Перша — неправильний клас захисту на iOS. FileProtectionType.complete означає: файл недоступний, поки пристрій заблоковано. Але якщо додаток отримує push-сповіщення у фоні і намагається читати базу — крэш. Розробники в паніці змінюють на completeUnlessOpen або взагалі прибирають захист. Правильне рішення — розділити дані: критичні під .complete, фонові операції під .completeUnlessOpen.
Друга — зберігання ключа поруч з даними. Зустрічали кейс, де ключ шифрування бази лежав у тій же директорії, що й зашифрована база, просто у файлі key.bin. Це не шифрування, це перейменування.
Третя — використання пароля користувача безпосередньо як ключа. AES вимагає 128 або 256 біт. Пароль «qwerty123» — це не ключ. Потрібен KDF: PBKDF2 з мінімум 100 000 ітерацій або Argon2id. На iOS — CommonCrypto.CCKeyDerivationPBKDF, на Android — SecretKeyFactory з PBKDF2WithHmacSHA256.
| Шар | iOS | Android |
|---|---|---|
| База даних | SQLCipher + CoreData | SQLCipher + Room |
| Файли | CryptoKit AES-GCM | javax.crypto.Cipher AES-GCM |
| Секрети | Keychain (Secure Enclave) | Android Keystore (TEE/SE) |
Джерело: документація SQLCipher (sqlcipher.net) та Apple Keychain Services
Інтеграція з біометрією
Просунутий варіант — ключ шифрування бази захищений біометрією через Keystore/Keychain. На Android: KeyGenParameterSpec.Builder з .setUserAuthenticationRequired(true) і .setUserAuthenticationParameters(0, KeyProperties.AUTH_BIOMETRIC_STRONG). Ключ створюється один раз при першому вході з біометрією, потім при кожному відкритті додатку користувач проходить аутентифікацію, ключ розблоковується з Keystore, база відкривається.
На iOS аналогічно через kSecAttrAccessControl з SecAccessControlCreateWithFlags і флагом .biometryAny або .biometryCurrentSet. Різниця: .biometryCurrentSet інвалідує ключ при додаванні нових відбитків — це важливо для банківських додатків (згідно з офіційною документацією Apple).
Що входить у роботу
Повний цикл впровадження шифрування під ключ (вартість від $500 до $1500):
- Інвентаризація даних, що зберігаються, та класифікація за критичністю.
- Вибір схеми ключів та інтеграція з Keystore/Keychain.
- Реалізація шару шифрування для бази, файлів та секретів.
- Міграція існуючих даних (якщо є).
- Тестування всіх сценаріїв: оновлення додатку, відновлення з бекапу, зміна біометрії.
- Документація та навчання вашої команди.
Процес
Починаємо з інвентаризації: що і де зберігається, чи є вже шифрування, які дані потрапляють під вимоги (PCI DSS, GDPR, локальні нормативи). Далі — вибір схеми ключів, реалізація шару шифрування, інтеграція з існуючим сховищем. Окремо — тестування сценаріїв: оновлення додатку, відновлення з бекапу, зміна біометрії користувачем.
Термін залежить від обсягу даних та наявності існуючої схеми зберігання. Якщо база вже є і потрібна міграція на SQLCipher — 3–5 днів з урахуванням тестування. Шифрування файлового кешу та Keychain-інтеграція — додатково 1–2 дні. Повна схема з нуля для нового проєкту — швидше.
Оцінимо ваш проєкт безкоштовно. Зв'яжіться з нами — ми проаналізуємо поточну схему зберігання і запропонуємо оптимальне рішення з гарантією безпеки.







