[官网文档翻译]Flutter持久化库drift - 其它引擎 - 加密

11,684 阅读3分钟

「这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战」。

Flutter持久化库drift(原moor)官方文档翻译汇总 - 掘金 (juejin.cn)

本文翻译自 drift 的 官方文档 Encryption (simonbinder.eu)

肉翻多有不足,不吝赐教。


重要通知: moor 已改名为 drift 。更多信息[中文]。

加密

在加密的数据库上使用 drift 。

有两种方式可以在加密的数据库上使用 drift 。encrypted_moor 包和 moor_flutter 类似,使用用 java 写的平台插件。作为选择,可以使用基于 ffi 实现的 sqlcipher_flutter_libs 包。

使用 encrypted_moor

从版本1.7开始,我们有一个版本的 drift , 可以通过使用 sqflite_sqlcipher 库(由@davidmartos96开发)的加密数据库。要使用这个版本的 drift ,需要从 pubspec.yaml 中移除 moor_flutter 的依赖,然后替换为下面的内容:

dependencies:
  drift: ^1.0.1
  encrypted_moor:
   git:
    url: https://github.com/simolus3/moor.git
    path: extras/encryption 

在 APP 中,不再导入 package:moor_flutter/moor_flutter (或 package:drift/native.dart ,应该导入 package:drift/drift.dart 和 package:encrypted_moor/encrypted_moor.dart

最后,把 FlutterQueryExecutor (或 NativeDatabase) 替换为 EncryptedExecutor

在 Android 和 iOS 上额外的安装

为了使SQLCipher 能够正常运转,需要在工程中做一些额外的步骤。 例如:在 Android 上配置ProGuard 用于发布。

阅读指南 ( 用法和安装指南可以忽略,它们会在 moor 内部处理)

NativeDatabase 的 加密版

可以使用新的带加密执行器的 drift/native 库。这允许在多个平台上使用加密的 drift 数据库,特别是对于桌面应用。

安装

要使用 sqlcipher,需要添加 sqlcipher_flutter_libs 依赖:

dependencies:
  sqlcipher_flutter_libs: ^0.5.0

如果已经添加了 sqlite3_flutter_libs 依赖,先删除这个依赖。 sqlite3_flutter_libs 和 sqlcipher_flutter_libs 并不兼容,因为它们各自提供了一个不同的 sqlite3 原生 api 的集合。

在 Anrdoid 上,需要改变 sqlite3 包的打开行为,使用加密的库替换常规的 libsqlite3.so

import 'package:sqlite3/open.dart';

// 使用 drift 之前调用此方法
void setupSqlCipher() {
  open.overrideFor(
      OperatingSystem.android, () => DynamicLibrary.open('libsqlcipher.so'));
}

在后台数据库中使用 drift 时,也需要在后台 isolate 中调用 setupSqlCipher

在 iOS 和 MacOS 上,不需要其它额外的安装 - 只需要依赖 sqlcipher_flutter_libs

在 Windows 和 Linux 上,当分发应用时,现在需要手动将 SQLCipher 的一个版本包含进去。更多信息参考这里。 代替包含 sqlite3.dll 或 libsqlite3.so,需要把各自版本的 SQLCipher 包含进去。

使用

SQLCipher 实现了 sqlite3 的 C 的 api ,这意味着可以不作任何修改,继续使用 sqlite3 包或 drift/ffi 。它们都和 sqlcipher_flutter_libs 完全兼容。

实际上要加密一个数据库,必须在使用前设置一个密钥。在 drift 文件中有个不错的设置密钥的地方,就是 NativeDatabasesetup 参数,在任何情况下这都会在 drift 使用数据库之前运行。

NativeDatabase(
  File(...),
  setup: (rawDb) {
    rawDb.execute("PRAGMA key = 'passphrase';");
  }
);

重要注意事项

在原生端, SQLCipher 和 sqlite3 相互冲突。如果应用的包同时依赖这两个本地库,实际上从中得到的一个可能在一些平台上变成未定义的。特别是,如果依赖 sqlcipher_flutter_libs 和另外的依赖 sqflite 的包,仍然会得到常规的不支持加密的 sqlite3

由于这个原因,建议在运行时检查 cipher_version 是否可用。

bool _debugCheckHasCipher(Database database) {
  return database.select('PRAGMA cipher_version;').isNotEmpty;
}

接下来,在使用数据库之前添加一个 assert(_debugCheckHasCipher(database)) 。合适的地方是 NativeDatabasesetup 参数:

NativeDatabase(
  File(...),
  setup: (rawDb) {
    assert(_debugCheckHasCipher());
    rawDb.execute("PRAGMA key = 'passphrase';");
  }
);

如果检查到加密版本不可用,可以看下这里的文档中有什么建议。