The recent release of SQLCipher 4 introduces many new performance and security enhancements for applications that use SQLCipher for secure local data storage. However, the introduction of new default algorithms, increased KDF iterations and a larger page size means that SQLCipher 4 will not open older databases by default.
This document provides guidance on the upgrade options available to applications that have previously integrated SQLCipher versions 1 through 3.
Option 1: Database File Migration
SQLCipher provides a very convenient way to perform an “in place” migration of a SQLCipher database using
PRAGMA cipher_migrate. This does all the work of updating the database file format with a single SQL statement. After migration the database will use all of the latest default settings so an application can immediately benefit from improved performance and security.
PRAGMA cipher_migrate be run a single time immediately after the key is provided (i.e. via
PRAGMA key in order to upgrade the database. This would normally occur on the first run after the application is upgraded to perform a one-time conversation.
After the migration is complete the application will no longer need to call the command again on subsequent opens.
PRAGMA key = '<key material>'; PRAGMA cipher_migrate;
The PRAGMA will return a single row with the value
0 after successful completion of the migration process. The migrated database will remain open and use the same filename.
Note: When opening a database connection to run
PRAGMA cipher_migrate, you must include the
SQLITE_OPEN_CREATE flag as the migration process will temporarily attach a new database during the migration process.
Option 2: Backwards Compatibility
The second option is to use the new SQLCipher 4 library, but use all of the SQLCipher 3 (or earlier) settings. This requires an application to execute PRAGMA statements immediately after keying the database that will match the settings originally used to create the database.
Starting with SQLCipher 4.0.1, you can use the new
cipher_compatibility feature. Passing values 1, 2, or 3 to the PRAGMA will cause SQLCipher to operate with default settings consistent with the respective major version number for the current connection. For example, the following will cause SQLCipher to treat the current database as a SQLCipher 3.x database:
PRAGMA cipher_compatibility = 3;
It is also possible to use the similar
cipher_default compatibility PRAGMA to set the value for the lifetime of a process before key operations are invoked.
Applications are also free to explicitly manage the low-level page size, KDF, and algorithm settings. This option is more verbose, but works effectively the same way. The appropriate settings vary by the SQLCipher version used previously:
PRAGMA cipher_page_size = 1024; PRAGMA kdf_iter = 64000; PRAGMA cipher_hmac_algorithm = HMAC_SHA1; PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;
PRAGMA cipher_page_size = 1024; PRAGMA kdf_iter = 4000; PRAGMA cipher_hmac_algorithm = HMAC_SHA1; PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1;
PRAGMA cipher_page_size = 1024; PRAGMA kdf_iter = 4000; PRAGMA cipher_hmac_algorithm = HMAC_SHA1; PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1; PRAGMA cipher_use_hmac = OFF;
When using legacy settings, the library will be operating in a compatibility mode with a previous release. Thus, an application will not be taking advantage of all the security improvements available in the new version. Instead the application will function with the same level of security as the original SQLCipher version.
It is important to note that since no migration is occurring, compatibility statements must be executed every time a database is opened. It is, however, possible to set process-level defaults using the
cipher_default_ versions of these PRAGMAs (e.g.
PRAGMA cipher_default_kdf_algorithm). This will change the default settings for the lifetime of the process. Please refer to the SQLCipher API for a full list of available settings.
Option 3: Custom Export Migration
When an application uses a custom configuration or non-default settings it is possible to use the
sqlcipher_export() convenience function for fine-grained control over the migration process. The general procedure for using
- Open a connection to the existing database and set the appropriate backward compatibility PRAGMAs as described in Option 2.
- Attach a new encrypted database, which will use the new settings by default.
- Set any custom PRAGMAs for the new attached database (optional).
sqlcipher_export()to “copy” the data from the main database to the new attached database.
- After export, detach the new database, and close the main database connection.
- Re-open the new database, optionally deleting the original database and/or renaming the new database as appropriate.
The following example demonstrates the statements required to migrate a SQLCipher 3 database using
sqlcipher_export(). At the end of the process the migrated database will be named sqlcipher-4.db.
PRAGMA key = '<key material>'; PRAGMA cipher_page_size = 1024; PRAGMA kdf_iter = 64000; PRAGMA cipher_hmac_algorithm = HMAC_SHA1; PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1; ATTACH DATABASE 'sqlcipher-4.db' AS sqlcipher4 KEY '<key material>'; SELECT sqlcipher_export('sqlcipher4'); DETACH DATABASE sqlcipher4;
Choosing the Right Approach
Applications are free to select an upgrade approach that most closely meets their requirements. However, the recommended approach is to use Option 1 to take advantage of new features while minimizing the complexity of the application code required for migration.