davidmartos96 / sqflite_sqlcipher

SQLite flutter plugin
BSD 2-Clause "Simplified" License
96 stars 41 forks source link

How the encryption happens? #74

Closed Shruthi125 closed 11 months ago

Shruthi125 commented 11 months ago

When a database is given, that is not getting encrypted but simply copies. How to resolve that and how does the encryption happen?

davidmartos96 commented 11 months ago

What do you mean by "simply copies"? In order to encrypt you need to provide the password parameter to openDatabase. An empty password would work like regular SQLite.

Shruthi125 commented 11 months ago

After giving the password also its not working. And is there any database named sqlite_master in this?

davidmartos96 commented 11 months ago

Not a database named sqlite_master, but a table. It exists in all sqlite databases. Doing SELECT * FROM sqlite_master should work after the database is opened.

What platform are you using? Android, iOS,... Make sure to delete the database/reinstall the app after changing the password parameter, otherwise it will try to use a different password to an already created database

Shruthi125 commented 11 months ago

currently using Android , on debugging this is the exception occured : Exception has occurred. SqfliteDatabaseException (DatabaseException(SQL logic error: , while compiling: select count(*) from sqlite_master;))

davidmartos96 commented 11 months ago

Could you provide the full error stacktrace?

Are you trying to open an already encrypted database from assets? Or is the database created from scratch in the device?

Shruthi125 commented 11 months ago

I have created a db with data but not encrypted. I want that to be encrypted and then open.

D/Sqflite (32028): Opening db in /data/user/0/com.davidmartos96.example/databases/asset_example.db with PRAGMA cipher_migrate I/flutter (32028): DatabaseException(SQL logic error: , while compiling: select count(*) from sqlite_master;) I/flutter (32028): #0 SqfliteSqlCipherDatabaseFactoryImpl.wrapDatabaseException (package:sqflite_sqlcipher/src/factory_sql_cipher_impl.dart:44:9) I/flutter (32028): I/flutter (32028): #1 SqfliteDatabaseMixin.openDatabase (package:sqflite_common/src/database_mixin.dart:777:9) I/flutter (32028): I/flutter (32028): #2 SqfliteDatabaseMixin.doOpen (package:sqflite_common/src/database_mixin.dart:879:22) I/flutter (32028): I/flutter (32028): #3 SqfliteDatabaseOpenHelper.openDatabase (package:sqflite_common/src/database.dart:46:7) I/flutter (32028): I/flutter (32028): #4 SqfliteDatabaseFactoryMixin.openDatabase. (package:sqflite_common/src/factory_mixin.dart:110:18) I/flutter (32028): I/flutter (32028): #5 ReentrantLock.synchronized. (package:synchronized/src/reentrant_lock.dart:37:18) I/flutter (32028): I/flutter (32028): #6 BasicLock.synchronized (package:synchronized/src/basic_lock.dart:33:16) I/flutter (32028): I/flutter (32028): #7 new SqlCipherTestPage. (package:sqflite_sqlcipher_example/sqlcipher_test_page.dart:89:

davidmartos96 commented 11 months ago

@Shruthi125 That stacktrace comes from the example project. Did you change the database from the example?

I think it would be better if you can share a sample repo with what you are doing. Otherwise it is very hard to tell what's going on.

Shruthi125 commented 11 months ago

test('Open asset database', () async { var databasesPath = await getDatabasesPath(); //gets the path to the databases directory n assigns to var

  var path = join(databasesPath, 'asset_example.db');//constructs a path var by joining the 'databasespath' var n the filename
  // delete existing if any in the path to ensure a clean state before copying the asset database.

  await deleteDatabase(path);
  // Make sure the parent directory exists
  try {
    //Checks if the parent directory of the path exists and creates it if it doesn't. 
    await Directory(dirname(path)).create(recursive: true);
  } catch (_) {}

  // Copy filename from asset directory from 'rootBundle' object. rootBundle provides access to the asset files in flutter

       ****//I changed the db name just here and have added that to the dependency too**** 
        var data =
      await rootBundle.load(join('assets', 'Sample1.db'));    
  // Converts the loaded asset file's data into a list of integers (List<int>). This represents the binary data of the database file.    
  List<int> bytes =
      data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
  await File(path).writeAsBytes(bytes, flush: true);

  // open the copied database providing path n password for decryption if the database is encrypted with SQLCipher.
  var db = await openDatabase(path,password: '1234');

  /*resulting records are stored in a list of maps (List<Map<String, dynamic>>), where each map represents a record with
  column names as keys and corresponding values.*/
  List<Map<String, dynamic>> list = await db.rawQuery('SELECT * FROM state');
  print('list $list'); 
  //validation step
  expect(list.first['state_name'], 'JAMMU'); //assert the value to be the string 'simple value'
  await db.close();
});
davidmartos96 commented 11 months ago

What that code does is open an already encrypted database with the password 1234. If you are trying to open a database without password or without a different password it will not work.

Shruthi125 commented 11 months ago

Ok. Thank you. So I have a database with tables and related content in it. And I want to encrypt the data in that database. Please let me know how do I do that using the code

davidmartos96 commented 11 months ago

@Shruthi125 In that case you need to use SQLCipher CLI in a desktop environment to encrypt it, then use it as an asset in the Flutter app. Refer to this for a sample script: https://github.com/davidmartos96/sqflite_sqlcipher/issues/20#issuecomment-636363796

Shruthi125 commented 11 months ago

Ok. Thankyou. I am using vscode in Windows desktop. So any further requirements?

davidmartos96 commented 11 months ago

Ok. Thankyou. I am using vscode in Windows desktop. So any further requirements?

You need to install/build SQLCipher for Windows so that from the command line you can run sqlcipher. You can then adapt the script I shared which uses bash to a bat file to run it on Windows.

Shruthi125 commented 11 months ago

I hope this is the script.

!/bin/bash

if [ -z "$1" ] then echo "No argument supplied" exit fi

echo "Encrypting $1"

rm my_app_database.db

echo "ATTACH DATABASE 'encrypted.db' AS encrypted KEY '123456ABC'; SELECT sqlcipher_export('encrypted'); DETACH DATABASE encrypted;" | sqlite3 $1

echo echo "Copying to Flutter project" rm C:/app_mobile/assets/databases/my_app_database.db

cp encrypted.db C:/app_mobile/assets/databases/my_app_database.db rm my_app_database.db

echo "Done."

davidmartos96 commented 11 months ago

@Shruthi125 Yes, that's the one.

Shruthi125 commented 11 months ago

I followed this video https://www.youtube.com/watch?v=SFHGeetZ0po and did accordingly, but the sqlite3.exe file dint generate. Please let me know the reason for that.

davidmartos96 commented 11 months ago

@Shruthi125 I'm sorry but I wouldn't be able to help you with that. I have experience building SQLCipher in a Linux machine, not Windows.

Shruthi125 commented 11 months ago

Ok. Thank you

davidmartos96 commented 11 months ago

Closing as this doesn't appear to be a problem with sqflite_sqlcipher itself