davidmartos96 / sqflite_sqlcipher

SQLite flutter plugin
BSD 2-Clause "Simplified" License
102 stars 46 forks source link

sqlcipher_export() support #33

Closed ramtinq closed 3 years ago

ramtinq commented 3 years ago

Hi, thanks for this great & simple package. I just wanted to know if there could be a way to encrypt a sqlite database using this package, like in sqlcipher's sqlcipher_export() function:

.open 'plain.db' ATTACH DATABASE 'encrypted.db' AS encrypted KEY 'secret'; SELECT sqlcipher_export('encrypted'); DETACH DATABASE encrypted;

Any suggestion is appreciated.

davidmartos96 commented 3 years ago

@ramtinq You could use precisely that SqlCipher function. You have the Sqflite API at hand to do anything you need. For attaching and detaching you can use execute. https://pub.dev/documentation/sqflite/latest/sqlite_api/DatabaseExecutor/execute.html

davidmartos96 commented 3 years ago

And to open it initially, you can pass an empty string as password

davidmartos96 commented 3 years ago

@ramtinq In any case, do you have a specific use case to need to encrypt a database from the app itself? Or do you need to encrypt a database and bundle it into the app? For the latter you need to install the Sqlcipher tooling for your desktop environment and run the sqlcipher_export() from there.

ramtinq commented 3 years ago

thanks for your reply. Yes it worked. I thought maybe not all SqlCipher's functionality is available in this package. Thought it would just work for reading encrypted sqlite databases. Your package is great! Thanks!

alaincruz06 commented 2 years ago

Hi @ramtinq @davidmartos96 I'm facing a similar problem to export an encrypted database using sqflite_cipher. I've had tried the code with sqflite (without encryption) and it works fine (I can export my .db from my app without troubles and I'm able to use it on another device). I'm using two ways (working well on sqflite), but when I try with sqflite_cipher, I can't open my exported file "database.db" (it looks like if the password is incorrect, using the same password from the original file):

First approach using package share_plus:

import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';

DBProvider().database.close();

final databasesPath = await getDatabasesPath();
final dbPath = join(databasesPath, "database.db");

final File file = File(dbPath);
await Share.shareFiles([file.path]);

Second approach using the medium article fromr @sohelakhtar23 Flutter Sqflite database Backup & Restore (import/export DB):

DBProvider().database.close();

final dbFolder = await getDatabasesPath();
File source1 = File('$dbFolder/database.db');
Directory? copyTo = await getExternalStorageDirectory();

String newPath = "${copyTo!.path}/database.db";
await source1.copy(newPath);

I'm currently exploring other ways but if you found any error, need aditional info or have some suggestions I would appreciate it. Thanks for reading this (PS: I don't know if a closed PR will notify you)

davidmartos96 commented 2 years ago

@alaincj Where are you opening the exported db from? It could be that you don't have SQLCipher there. To be sure run the following: PRAGMA cipher_version. It should give you something like: "SQLCipher community version"

alaincruz06 commented 2 years ago

I'm using an imported db file using package File Picker and another imports (included package:sqflite_sqlcipher). Works with sqflite without encryption.

import 'dart:io';
import 'dart:typed_data';
import 'package:path/path.dart';
import 'package:sqflite_sqlcipher/sqflite.dart';

 Future<void> initImportedDb(Uint8List bytes) async {
    final databasesPath = await getDatabasesPath();
    final path = join(databasesPath, 'database.db');

    await deleteDatabase(path);
    try {
      await Directory(databasesPath).create(recursive: true);
    } catch (_) {}

    await File(path).writeAsBytes(bytes, flush: true).whenComplete(() async {
      _database = await openDatabase(path, password: "1234");
    });
  }

Running PRAGMA cipher_version: SQLcipher version: 4.4.2 community

Also, I'm not having any troubles working with the opened db or saving changes in debug or release mode.

davidmartos96 commented 2 years ago

@alaincj It should work. I'm doing exactly that in my app. Did you run cipher_version in the device that doesn't open?

You can open a memory db in that device.

final db = await openDatabase(inMemoryDatabasePath);
final rows = await db.rawQuery("PRAGMA cipher_version");
print(rows);
alaincruz06 commented 2 years ago

Eureka!!!!! In fact I'am able to use the exported db on the same app (as you say earlier) wich is one of my objectives , and I can run queries without troubles (cipher_version included). The problem appears when I copy that db to my laptop, and try to open it using a Database Browser software. Shame on me, for real, shame on me, I was using several database softwares (but outdated) and they couldn't open that exported db because of the changes and the newer versions in encryption. I just download a newer version and it works!! It was just the migration changes and old versions of database browsers. Final conclusion: Keep yourself up to date!! PS: Sorry for the inconveniences I gave you. And great package too!!! Happy coding

davidmartos96 commented 2 years ago

Eureka!!!!! In fact I'am able to use the exported db on the same app (as you say earlier) wich is one of my objectives , and I can run queries without troubles (cipher_version included). The problem appears when I copy that db to my laptop, and try to open it using a Database Browser software. Shame on me, for real, shame on me, I was using several database softwares (but outdated) and they couldn't open that exported db because of the changes and the newer versions in encryption. I just download a newer version and it works!! It was just the migration changes and old versions of database browsers. Final conclusion: Keep yourself up to date!! PS: Sorry for the inconveniences I gave you. And great package too!!! Happy coding

Glad to hear you got it working 😄