AES-256/GCM encryption for Android images and databases, backed by Android Keystore.
- Image/file encryption — AES-256/GCM with streaming support for large files
- Bitmap encryption — encrypt/decrypt Android Bitmaps directly to/from files
- Key management — hardware-backed keys via Android Keystore with rotation and recovery
- Database encryption — SQLCipher integration with Room, using Keystore-protected keys
- Password hashing — PBKDF2-HMAC-SHA256 for password verification
- In-place encryption — safe to encrypt a file to itself (uses temp file internally)
| Layer | Algorithm | Key Storage |
|---|---|---|
| Image encryption | AES-256/GCM, 128-bit tag, 12-byte IV | Android Keystore (hardware-backed) |
| Database encryption | SQLCipher (AES-256-CBC) | Random key encrypted with Keystore master key, stored in SharedPreferences |
| Password hashing | PBKDF2-HMAC-SHA256, 10K iterations | N/A (verification only) |
Keys never leave the Android Keystore. The IV is prepended to each ciphertext, making encrypted files self-contained.
val key = KeyManager.getOrCreateImageKey() val encryption = ImageEncryption(key) // Encrypt a file encryption.encryptFile(inputFile, outputFile) // Decrypt it back encryption.decryptFile(outputFile, decryptedFile) // Encrypt a Bitmap directly encryption.encryptBitmapToFile(bitmap, encryptedFile, quality = 90) // Decrypt back to Bitmap val bitmap = encryption.decryptFileToBitmap(encryptedFile)
@Database(entities = [MyEntity::class], version = 1) abstract class MyDatabase : RoomDatabase() { abstract fun myDao(): MyDao } val db = EncryptedDatabaseBuilder.build( context = applicationContext, klass = MyDatabase::class.java, name = "my_encrypted_db" )
val salt = PasswordUtils.generateSalt() val hash = PasswordUtils.hashPassword("user_password", salt) // Store salt + hash; verify by re-hashing and comparing
The database key includes retry logic for transient Keystore errors. For user-initiated recovery (e.g., after a factory reset that invalidates Keystore keys):
val db = EncryptedDatabaseBuilder.build( context = context, klass = MyDatabase::class.java, name = "my_db", allowKeyRegeneration = true // WARNING: old data becomes unreadable )
| Library | Purpose |
|---|---|
net.zetetic:sqlcipher-android |
SQLCipher database encryption |
androidx.room:room-runtime |
Room database abstraction |
androidx.sqlite:sqlite-framework |
SQLite support |
Copy the com.simonshub.encryptedstorage package into your project, or include as a module dependency.
MIT License. See LICENSE for details.