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 comparingThe 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.