davidmartos96/sqflite_sqlcipher

usage with the sqflite_common api?

ramsestom opened this issue · 11 comments

Trying to use sqflite_sqlcipher as a replacment of sqflite in a third party library that uses the sqflite_common api to open a databse
It uses the DatabaseFactory.openDatabase(String path, {OpenDatabaseOptions? options}); method to open the database. So is it possible to pass the password field to this function as an option?

Here is the code of the function used to open a database:

Future<sqflite.Database> open(String path, List<Migration> migrations, [Callback? callback, String? password]) async {
    final databaseOptions = sqflite.OpenDatabaseOptions(
      version: 1,
      onConfigure: (database) async {
        await database.execute('PRAGMA foreign_keys = ON');
        await callback?.onConfigure?.call(database);
      },
      onOpen: (database) async {
        await callback?.onOpen?.call(database);
      },
      onUpgrade: (database, startVersion, endVersion) async {
        await MigrationAdapter.runMigrations(
            database, startVersion, endVersion, migrations);

        await callback?.onUpgrade?.call(database, startVersion, endVersion);
      },
      onCreate: (database, version) async {
        await database.execute(
            'CREATE TABLE IF NOT EXISTS `Task` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `message` TEXT NOT NULL)');

        await callback?.onCreate?.call(database, version);
      },
    );
    return sqfliteDatabaseFactory.openDatabase(path, options: databaseOptions);
  }

I added it the optional String? password parameter but now I would like to pass it along to the DatabaseFactory.openDatabase() sqflite_common API function

@ramsestom What do you mean? Could you give an example?
You can use the sqflite functionality API after having opened the encrypted database.

@davidmartos96
Sorry I miss-pressed the enter key before typing my first comment ;)
I edited it

@ramsestom Doing that you are basically reimplementing the Dart side of sqflite_sqlcipher. Under the hood this package uses sqflite_common and has a databaseFactory that returns an encrypted Database.
Any reason for not using the openDatabase method from sqflite_sqlcipher directly?

Take a look at this file: https://www.github.com/davidmartos96/sqflite_sqlcipher/tree/master/sqflite%2Flib%2Fsrc%2Fdatabase_sql_cipher_impl.dart

As you can see, the password is injected in the openDatabase platform channel method.

Does the openDatabase method from sqflite_sqlcipher have an OpenDatabaseOptions options optional parameter?

@ramsestom No, that would be the factory.
This is what gets called underneath openDatabase:

image

In any case, note that even if you used the sqflite_common API for SQLCipher, you would be missing the native implementation (android, ios and macos).
Also, SQLCipher is a superset of SQLite, so you can open normal databases (without encryption) with SQLCipher.
I don't yet quite understand the situation. I think you can simply swap the sqflite dependency.

@ramsestom Sorry, I didn't see the code above, now I understand better.
I think you could use the sqfliteSqlCipherDatabase factory (https://pub.dev/documentation/sqflite_sqlcipher/latest/sqflite/databaseFactory.html)
and the SqlCipherOpenDatabaseOptions which is a subclass of the regular Options (https://pub.dev/documentation/sqflite_sqlcipher/latest/sqlite_api/SqlCipherOpenDatabaseOptions-class.html)

But, note that if you are building a general solution for migrations, you need the SqlCipher native library. Importing sqflite_sqlcipher would be enough for it to work

OK the factory use a String? password option field so writting it in my databaseOptions object should just work fine ;)

to clarify the situation:
I already swaped the sqflite dependency in the third part library (https://github.com/vitusortner/floor) I want to migrate to sqflite_sqlcipher. But the code of this lib is relying on calling the sqflite_common api to connect to the database (because it uses as DatabaseFactory the SqfliteDatabaseFactory from sqflite for Android and iOS and another one for desktop platforms. So my problem was just to know how to pass the password option field to the SqfliteDatabaseFactory from sqflite_sqlcipher that would replace the SqfliteDatabaseFactory from sqflite. But you gave me the solution with the code you pasted

Is there a way to declare sqflite_sqlcipher as if it where a packaged name sqflite in my pubspec.yaml so I don't have to modify every sqflite import to sqflite_sqlcipher in my third party library code?

@ramsestom I don't think there is, but you can do a good old find and replace 😅

On a side note, if you are looking for desktop support check out the following post. #42

Maybe you don't need this library at all.