This repository contains the code accompanying the article
Migrating from Encrypted SharedPreferences to Jetpack DataStore.
It showcases a step-by-step transition from Encrypted SharedPreferences to Jetpack DataStore.
Migrating from Encrypted SharedPreferences to Jetpack DataStore improves data security and performance in Android apps.
This repository demonstrates each migration step in different branches:
- branch-1-initial-setup – Initial implementation using
EncryptedSharedPreferences. - branch-2-introduce-datastore – Introduced
DataStorewithout migration. - branch-3-migration-setup – Set up migration logic from
EncryptedSharedPreferencestoDataStore. - branch-4-migration-implementation – Implemented migration logic.
- branch-5-final-version – Final version with a complete migration process.
The final version includes:
- ✅ Fully implemented migration from
EncryptedSharedPreferencestoJetpack DataStore. - ✅ Secure encryption using AES-GCM.
- ✅ Proper key management with MasterKey and a keyset similar to Tink library.
-
Initial Setup
- Open
AppComponent.ktand set the preferences provider toSharedPreferencesProvider:mainActivity.preferences = sharedPreferencesProvider - Run the application and enter some data to be stored.
- Open
-
Switch to DataStore with Migration
- Open
AppComponent.ktand replace the preferences provider withDataStorePreferencesProvider:mainActivity.preferences = dataStorePreferencesProvider - Run the application again. The stored data will be migrated to
Jetpack DataStore.
- Open
-
Verify Migration Success
- Check the logs using the tag
"TAG11". The logs will show which data has been successfully migrated toDataStore.
- Check the logs using the tag
The final version ensures secure data storage by implementing:
- AES-GCM encryption for securing stored values.
- MasterKey creation for key management, similar to how Tink library handles encryption.
- AES-256 encryption for key protection, ensuring that encryption keys remain secure.
- Encrypted keyset storage, making sure keys are safely managed and protected.
-
Keys encryption (AES-256-SIV-CMAC):
- Keys are encrypted using AES-256-SIV-CMAC, where the IV (initialization vector) is deterministically computed.
- This means that for the same input, the ciphertext will always be the same.
- The underlying mode is AES/CTR/NoPadding, a stream cipher mode without built-in integrity checks.
-
Values encryption (AES-256-GCM):
- Values are encrypted using AES-256-GCM, where the IV is randomly generated for each encryption operation.
- This ensures that even for the same input, the ciphertext will always be different.
- The underlying mode is AES/GCM/NoPadding, which includes built-in authentication (tag) to prevent data tampering.
📂 app
├── 📂 data
│ ├── SharedPrefsManager.kt // Handles EncryptedSharedPreferences
│ ├── DataStoreManager.kt // Handles Jetpack DataStore
│ ├── DataMigration.kt // Migration logic
│ └── DataModel.proto // Proto DataStore schema
├── 📂 ui
│ ├── MainActivity.kt // Demonstrates data usage
│ └── SettingsFragment.kt // Settings screen using DataStore
- Clone the repository:
git clone https://github.com/KyrBabenko/encrypted-data-store-migration.git
- Checkout the final branch:
git checkout branch-5-final-version
- Open the project in Android Studio and run it.
- Kotlin
- Jetpack DataStore (Proto DataStore)
- EncryptedSharedPreferences
- AES-256-SIV-CMAC for key encryption
- AES-256-GCM for value encryption
- Coroutines & Flow
A detailed migration guide is available in the Medium article, Linkedin article.
This project is released under an open-source license with no restrictions.