Skip to content

Java|Kotlin 加密与配置

qiuwenchen edited this page Mar 7, 2024 · 1 revision

本文主要介绍如何对 WCDB 特定的数据库进行基本的配置,而加密也是配置的其中较常用的一项。

配置主要用控制数据库操作的行为。WCDB 对 SQLite 的数据库做了基本的配置,如 journal_modefullfsync 等,以满足 WCDB 的需求。同时,开发者也可以根据自己的需求,自定义配置项。

默认配置

WCDB 提供的默认配置为:

  1. PRAGMA locking_mode="NORMAL"
  2. PRAGMA synchronous="NORMAL"
  3. PRAGMA journal_mode="WAL"
  4. PRAGMA checkpoint_fullfsync=1
  5. PRAGMA temp_store=1
  6. SQLITE_DEFAULT_PAGE_SIZE=4096
  7. SQLITE_DEFAULT_WAL_SYNCHRONOUS=1
  8. SQLITE_DEFAULT_WAL_AUTOCHECKPOINT=0
  9. SQLITE_DEFAULT_SYNCHRONOUS=1
  10. SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=4194304

加密

加密功能可通过 setCipherKey 方法开启,它有多个重载版本,其中参数最多的版本为:

// 该接口等同于配置 PRAGMA cipher="xxx",PRAGMA cipher_page_size=xxx, PRAGMA cipher_compatibility=xxx
public void setCipherKey(byte[] key,            // 密码
                         int pageSize,          // 加密页大小
                         CipherVersion version) // 创建数据库的SQLCipher的主版本

其中,pageSize 是加密的页大小参数,SQLCipher 在 大部分设备上默认使用 4096,部分设备默认使用 1024。而 WCDB 则在所有平台上都适用 4096,以获得更好的性能。开发者一般不需要做特别的修改。对于通过其他方式创建的加密数据库,如果之前的页大小是1024,则在 WCDB 使用时,可手动设置为 1024 以确保解密成功。更多关于 cipher_page_size 的信息,可以参考其官方文档

version是创建数据库的 SQLCipher 的主版本,现在 SQLCipher 的主版本到 4 了,也是WCDB现在使用的默认版本。之前WCDB 1.x 版本使用的 SQLCipher 主版本是 3。不同的主版本使用的加密配置也是不一样的,要根据数据库创建时所用的SQLCipher版本来配置,才能打开数据库。更多关于 cipher_compatibility 的信息,可以参考其官方文档

如果开发者也不清楚实际的配置,可以通过canOpen接口来尝试多种配置。

// Java
Database database = new Database(filePath);
byte[] password = "password".getBytes(StandardCharsets.UTF_8);

// 设置加密接口应在其他所有调用之前进行,否则会因无法解密而出错
database.setCipherKey(password);

assert database.canOpen();
database.insertObject(sample, DBSample.allFields(), "sampleTable");
// Kotlin
val database = Database(filePath)
val password = "password".toByteArray(StandardCharsets.UTF_8)

// 设置加密接口应在其他所有调用之前进行,否则会因无法解密而出错
database.setCipherKey(password)

assert(database.canOpen())
database.insertObject<Sample>(sample, DBSample.allFields(), "sampleTable")

开启加密会有部分性能损耗,详情请参考 Benchmark 与性能一章。

值得注意的是,设置密码是一件很慎重的事情。对于已经创建且存在数据的数据库,无论是原本未加密想要改为加密,还是已经加密想要修改密码,都是成本非常高的操作,因此不要轻易使用。更多相关信息可以参考官方文档

自定义配置

除了上述配置,开发者还可以根据自己的需求,通过 setConfig方法设置其他配置。详细的配置列表可以参考 SQLite 的官方文档SQLCipher 的官方文档

setConfig方法有多中版本,其中参数最全版本的原型如下:

public void setConfig(String configName,       // 配置名称,同名的配置会互相覆盖
                      Config invocation,       // 数据库连接打开时的配置回调
                      Config unInvocation,     //数据库连接关闭时的配置函数
                      ConfigPriority priority) // 配置执行的优先级,优先级高的优先执行。WCDB自带配置的优先级为默认值。

以下是设置配置的一个例子:

// Java
database.setConfig("secure_delete", new Database.Config() {
    @Override
    public void onInvocation(Handle handle) throws WCDBException {
        StatementPragma pragma = new StatementPragma().pragma(Pragma.secureDelete).toValue(true);
        handle.execute(pragma);
    }
});
// Kotlin
database.setConfig("secure_delete") { handle ->
    val pragma = StatementPragma().pragma(Pragma.secureDelete).toValue(true)
    handle.execute(pragma)
}
Clone this wiki locally