在移动应用开发中,数据安全是重要考量,当应用涉及敏感信息(如用户凭证、财务数据、个人隐私)时,需对本地数据库进行加密保护,防止以下风险:
方案 | 加密层级 | 密钥管理 | 兼容性 | 性能开销 |
---|---|---|---|---|
SQLCipher | 数据库文件级AES加密 | 开发者自行管理 | 兼容Room/SQLite | 中等 |
Android Keystore | 密钥硬件级保护 | 系统级安全管理 | 需配合自定义加密 | 低 |
Realm Encryption | 数据库+文件双重加密 | 内置密钥管理 | 仅Realm数据库 | 较高 |
SQLite + AES | 手动实现字段级加密 | 完全自主控制 | 所有SQLite场景 | 高 |
// 添加SQLCipher扩展 implementation "net.zetetic:android-database-sqlcipher:4.5.0" // Room基础库 implementation "androidx.room:room-runtime:2.5.1" kapt "androidx.room:room-compiler:2.5.1"
// 定义加密密钥(推荐存储在Android Keystore) val key = "your-encryption-key-24chars" // 实际应动态生成 @Database(entities = [User::class], version = 1) abstract class AppDatabase : RoomDatabase() { abstract fun userDao(): UserDao companion object { fun buildEncryptedDB(context: Context): AppDatabase { return Room.databaseBuilder( context, AppDatabase::class.java, "app_db.db" ) .openHelperFactory(object : Factory { override fun create(config: SupportSQLiteDatabase.Params): SupportSQLiteOpenHelper { return SQLiteOpenHelper( config.context, config.name, null, config.callback.version, SQLiteDatabase.OPEN_READWRITE or SQLiteDatabase.ENCRYPT, key.toCharArray() // 使用密钥初始化 ) } }) .build() } } }
@Entity(tableName = "users") data class User( @PrimaryKey val id: Int, val name: String, val password: String // 存储加密后密码 ) @Dao interface UserDao { @Query("SELECT FROM users") suspend fun getAllUsers(): List<User> @Insert suspend fun addUser(user: User) }
SecureRandom
生成16/24/32字节密钥val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC val keyStore = KeyStore.getInstance("AndroidKeyStore") keyStore.load(null) val keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore") keyGenerator.init(keyGenParameterSpec) val encryptionKey = keyGenerator.generateKey()
setUserAuthenticationRequired(true)
强制生物识别认证优化方向 | 实施方案 |
---|---|
减少加密频率 | 批量操作代替单条CRUD |
索引优化 | 对频繁查询字段建立加密前索引(需注意明文索引泄露风险) |
内存缓存 | 使用LiveData 或Flow 缓存解密后的数据 |
分表存储 | 将高频访问表与低频访问表分离,采用不同加密策略 |
Q1:数据库文件被破解后是否能看到明文?
A1:SQLCipher采用AES-256加密整个数据库文件,未授权访问者只能看到密文二进制数据,需确保密钥未泄露。
Q2:如何迁移加密数据库版本?
A2:
Migration
中同时处理 schema变更和数据重加密 Fallback
机制兼容新旧密钥版本 val MIGRATION_FROM = 1 val newKey = generateNewKey() // 新密钥生成逻辑
migration.addMigrations(object : Migration(MIGRATION_FROM, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
// 1. 解密旧数据到内存
// 2. 使用新密钥重建数据库
// 3. 导入数据并重新加密
}
})