目录
- SQLCipher
- SQLiteCrypt
- 其它
SQLCipher
SQLCipher
是 SQLite
数据库的的开源扩展,使用了 256 位 AES 加密,支持跨平台、零配置、数据100%加密、加密开销低至 5 -15%、占用空间小、性能出色等优点,因此非常适合保护嵌入式应用程序数据库,并且非常适合移动开发。
关于 SQLCipher
的使用,官网提供了 SQLiteDatabase
的接入案例,鉴于官网已有 SQLiteDatabase
案例,这里则不再重复赘述,本文改为在 Room
中集成。
打开 app 目录下的 build.gradle
文件,添加插件和依赖
// 用到 kapt 必须添加该插件
apply plugin: 'kotlin-kapt'
dependencies {
// room
kapt("androidx.room:room-compiler:2.4.2")
implementation "androidx.room:room-ktx:2.4.2"
implementation("androidx.room:room-rxjava3:2.4.2")
// sqlcipher 数据库数据加密
implementation 'net.zetetic:sqlcipher-android:4.5.6@aar'
implementation 'androidx.sqlite:sqlite:2.2.0'
}
新建一个继承 RoomDatabase()
的类,设置 SQLiteOpenHelper
。
@Database(entities = [Classes::class, Students::class], version = 2, exportSchema = false)
abstract class SchoolDatabase : RoomDatabase() {
companion object {
var db: SchoolDatabase ?= null
// 单例模式的双重检查锁
fun getDataBase(context: Context) : SchoolDatabase{
if (db == null) {
synchronized(SchoolDatabase::class.java){
if (db == null){
// 使用 SQLCipher 加密
val factory = SupportOpenHelperFactory("database password".toByteArray())
db = Room.databaseBuilder(context.applicationContext, SchoolDatabase::class.java, "your database name")
.openHelperFactory(factory)
.build()
}
}
}
return db as SchoolDatabase;
}
}
}
编写完成数据库的增删改查相关代码后,运行项目并完成对数据写入操作。
使用 Android Studio
的 Device Explorer
功能,打开 data/data/your package name/database/
文件夹,就可以看到应用的数据库。
鼠标右键点击 your package name
下创建的数据库,选择 Save AS ...
保存到桌面,使用 SQLiteStudio
数据库工具打开,就会有这样的提示:无法添加数据库 C:/Users/XXX/Desktop/your database file:file is not a database
因为我们已经对数据库进行了加密,是不能直接对其进行访问的。需要更换数据类型为 SQLCipher
,并输入在代码中设置的数据库密码,点击 ok
后,就可以对数据库进行访问了。
如果未使用 SQLCipher
对数据库进行加密,数据库是可以直接访问的。
SQLCipher
除了能支持 SQLite
、Room
之外,还支持 GreeDAO
数据库。不支持 ObjectDB
。
下载 Demo
参考文档
SQLCipher 官网
在 Android 中集成 SQLCipher
SQLiteCrypt
SQLiteCrypt
为 SQLite
数据库添加了透明的 AES 256 加密支持。SQLiteCrypt
非常快,它只是使 SQLite
速度减慢几个百分点,因此您的用户甚至不会注意到它的存在。
SQLiteCrypt
也是一个可以免费使用的 SQLite
加密库,在它的官网下方,提供了 Linux
、Ubuntu
、Window
、.Net
、Android
等版本的 demo,SQLiteCrypt
并没有像 SQLCipher
那样提供了一个与 Room
库兼容的版本。Room
库是基于 Android
的SQLite API
构建的,而 SQLiteCrypt
是一个 SQLite
的 C 扩展,它需要使用其自带的 API 来打开和操作加密的数据库。
使用 SQLiteCrypt
需要引入 .so 库,以及 .aar 文件。
dependencies {
implementation(name:'android-database-sqlitecrypt-release', ext:'aar')
}
使用时,用的是 com.sqlitecrypt.database.SQLiteDatabase
进行创建数据库
public void initDb() {
File dbFile = this.getDatabasePath("test.db");
String dbPath = dbFile.getPath();
if(!dbFile.exists()) {
new File(dbFile.getParent()).mkdirs();
}
// 第二个参数为数据库的密码,可不填(即不设置加密),使用 SQLiteDatabase.changePassword(password) 加密
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbPath, "", null);
// 设置数据库的访问密码为 abc123
db.changePassword("abc123");
// 查询数据库里 student 的表
db.rawQuery("SELECT * FROM student", null);
// 插入一条数据
db.execSQL("insert into student(id,name) VALUES(1, 'Sparta');");
// 删除 student 表中 id = 1 的数据
db.delete("student", "id=1", null);
// 关闭数据库
db.close();
}
com.sqlitecrypt.database.SQLiteDatabase
与 android.database.sqlite.SQLiteDatabase
的用法基本一致,它们都有 execSQL
、rawQuery
的方法,只要有点数据库基础知识就可以写出可执行的 SQL 语句。
其它
上面提到的数据库加密框架都是可以免费使用,当然,他们也有付费版本。
我在写这篇博客之前,去了解了一些数据库加密的技术,有的博主提到一种方式:写入数据库前进行数据加密,取出来时解密。
这种方式看着是可行的,但 不可取
数据加密一般都是将一段字符转译为其它字符,例如:byte、String、二进制。众所周知的 MD5,知道吧?它是把字符转换成了16、32位长度的字符。不考虑解密,假设一个表有10个字段,这时候需要插入一条数据,那么就有 9 ~ 10 个字段需要调用 MD5 加密算法加密一次,这才只是10个字段,如果一个表有几十个字段呢?
如果这样搞,相较于上述两个加密方式来说,这种方式时间复杂度、空间复杂度都处于最差劲那一组,不仅如此,还增加了维护成本。
参考文档
SQLiteCrypt 官网