首页 > 解决方案 > 将数据库从 SQLite 更改为 SQLCipher 后升级应用程序时遇到问题

问题描述

我们有一个以前使用SQLite的移动应用程序,但出于安全目的,我们将其更改为SQLCipher以提供加密,但是当我第一次尝试安装应用程序时它可以正常工作,问题是当我尝试升级时应用程序。应用程序因以下堆栈跟踪而崩溃

Caused by: net.sqlcipher.database.SQLiteException: file is not a database: , while compiling: select count(*) from sqlite_master;
        at net.sqlcipher.database.SQLiteCompiledSql.native_compile(Native Method) .....

标签: sqliteandroid-sqlitesqlcipherandroid-databasesqlcipher-android

解决方案


最新版本为用于安全本地数据存储SQLCipher 4的应用程序引入了许多新的性能和安全增强功能。SQLCipher然而,新的默认算法的引入、增加的 KDF 迭代和更大的页面大小意味着 SQLCipher 4默认情况下不会打开旧数据库。

本文档提供有关可用于先前集成SQLCipher版本 1 至 3 的应用程序的升级选项的指南。

选项 1:数据库文件迁移

SQLCipher提供了一种非常方便的方式来执行数据库的“就地”迁移,SQLCipher使用PRAGMA cipher_migrate. 它完成了使用单个 SQL 语句更新数据库文件格式的所有工作。迁移后,数据库将使用所有最新的默认设置,因此应用程序可以立即受益于改进的性能和安全性。

PRAGMA cipher_migrate在提供密钥后立即运行一次(即通过sqlite3_key()PRAGMA key为了升级数据库。这通常会在升级应用程序以执行一次性对话后的第一次运行时发生。

迁移完成后,应用程序将不再需要在后续打开时再次调用该命令。

PRAGMA key = '<key material>';
PRAGMA cipher_migrate;

成功完成迁移过程后,PRAGMA将返回值为 0 的单行。如果迁移失败,将返回非零列值。成功后,迁移的数据库将保持打开状态并使用相同的文件名。

重要提示: cipher_migratePRAGMA可能很昂贵,因为它需要尝试打开每个版本的数据库以确定适当的设置。因此,应用程序不应在PRAGMA每次打开数据库时调用。相反,应用程序应使用 cipher_migrate API 文档中推荐的过程。

注意: SQLCipher对于 Android Java 用户:打开数据库连接以运行 PRAGMA cipher_migrate 时,必须包含该 SQLITE_OPEN_CREATE标志,因为迁移过程会在迁移过程中临时附加一个新数据库。

选项 2:向后兼容性

第二个选项是使用新SQLCipher 4库,但使用所有SQLCipher 3(或更早的)设置。这要求应用程序在键入与最初用于创建数据库的设置相匹配的数据库后立即执行 PRAGMA 语句。

从 开始SQLCipher 4.0.1,您可以使用新的 cipher_compatibility 功能。将值 1、2 或 3 传递给 PRAGMA将导致SQLCipher使用与当前连接的相应主要版本号一致的默认设置进行操作。例如,以下将导致SQLCipher将当前数据库视为SQLCipher 3.x数据库:

PRAGMA cipher_compatibility = 3;

在调用关键操作之前,也可以使用类似的 cipher_default 兼容性 PRAGMA来设置进程生命周期的值。

您可以在此处找到详细信息。


推荐阅读