-
Notifications
You must be signed in to change notification settings - Fork 384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Force quiting our app throws file is not a database
error at startup of the app
#1810
Comments
This sounds worrying - SQLCipher uses PBKDF2 to derive the key from a string, so it shouldn't consider a subset of the key only. This is definitely not the intended behavior. On what platforms are you running into this? I can't reproduce this on Android with this driver test: test('key test', () async {
final dir = await getApplicationDocumentsDirectory();
dir.createSync();
final file = File('${dir.path}/test.db');
if (file.existsSync()) file.deleteSync();
var db = sqlite3.open('${dir.path}/test.db');
void reOpen() {
db.dispose();
db = sqlite3.open('${dir.path}/test.db');
}
db.execute("PRAGMA key = '3d80ac84-6dff-40bb-b803-abeed6c5e297'");
db.execute('create table foo (bar);');
reOpen();
db.execute("PRAGMA key = '3d80ac84-6dff-40bb-b803-abeed6c5e297test'");
expect(
() => db.execute('select * from foo;'),
throwsA(isA<SqliteException>()
.having((e) => e.message, 'message', 'file is not a database')));
}); I tried running this and it gave me the expected exception. |
I have been testing on iOS today. Tomorrow I will do android. We do have a could apps that use this implementation with 8 million users. But they are all still using |
Same test works for me in the iOS simulator, I don't have an actual device to test on unfortunately. Let me know if there's more I can try out, so far I've only tested the underlying |
Could it be a difference between sqflite vs flutter_sql_libs? |
The iOS sqflite_sqlcipher implementation uses the FMDB library. |
@vanlooverenkoen Are you using |
We are using NativeDatabase |
We are also using isolates, maybe that has something to do with it? |
Just tested on our application with 8 million users. (using moor). It does throw an error I am now trying to figure out what the difference is between 2 codebases. |
We are experiencing a lot of strange issues with our current implementation. sometimes we get
But if we wait some time or restart of do some other work on your phone. and open the app again everything is file. |
The issue is happening on android & iOS |
@simolus3 is it normal that I get Also after a restart. (file is not removed) |
I also can't open my sqlite db in table plus. A password is requested. but after entering the password I can't do anything. |
Isolates shouldn't have an impact on this.
Absolutely not! I means that the database is running against the regular sqlite3 implementation instead of SQLCipher. That would also explain why the Just to be sure, you're using On iOS, you might have another pod linking the regular sqlite3 library. Linking both SQLCipher and sqlite3 into the same executable leads to undefined behavior (which could include a broken mixture of both libraries). Could you check something like this? (unfortunately I don't have too much native iOS development experience). |
This is our current implementation
|
This is what is added in our
|
We found that |
Hmm, still can't open the db.sqlite file in |
Still having |
Should our simulator databases be encrypted as well? |
On device I get: |
We did some more testing and found a possible issue that the file is not released correctly. |
Afected devices:
|
Not affected:
|
Just disabled our encryption. (removing the pragma key) |
We will now try:
To see if we can unlock the file by creating a copy of that file. and using the copied one. |
That made me think of https://sqlite.org/howtocorrupt.html#multiple_copies_of_sqlite_linked_into_the_same_application I'm not sure how applicable that is here since (presumably..) there's only one thread/process involved, but just pointing it out as something to keep in mind while debugging. |
Started removing each dependency one by one. Found out that it is
It can only be reproduced on release builds. because on iOS it is not possible to restart the app after killing it. |
@NicolaVerbeeck gave me this snippet to remove
I will be testing more the coming hours. |
@vanlooverenkoen Have you tried the solution from here? https://github.com/simolus3/sqlite3.dart/blob/master/sqlcipher_flutter_libs/README.md |
Incompatibilities with sqlite3 on iOS and macOS yes |
Testing opening the sqlite db in TablePlus:
|
@simolus3 is it possible to run a unit test with an encrypted database? or does that always have to be a driver test? |
Sure! It is possible by instructing the import 'package:sqlite3/open.dart';
import 'package:test/test.dart';
void main() {
setupAll(() {
open.overrideFor(OperatingSystem.linux, () => DynamicLibrary.open('libSQLCipher.so'));
// ...
});
} But note that these tests wouldn't have discovered this issue since that's about how SQLCipher is linked into an application, something that you'd only catch with a driver test. For smaller unit tests that should work though. |
Yes indeed. We are writing tests for our migration process To make sure we move everything correctly. |
But it seems that this issue is fixed with: |
The To help others, I'm thinking about recommending that snippet in the readme of |
Because we found this issue a couple of days before the release, it took some time to pinpoint where the issue was located. Regarding the documentation. I think it is good to add the snippet as well.
We also wrote a migration (at file level, not db level.) from the non-encrypted to the encrypted database. So that is possible as well. Because when using SQLCipher can also read non encrypted databases |
@simolus3 I don't think pods being compiled on their own will be an issue since the interface provided by both sqlite and sqlcipher is the same and linking only happens in the final executable creation step. Until someone decides to statically include the sqlite.c file in their pod, in which case everything breaks. |
I had this problem time ago and fixed it with your solution. However, it came back and it seems not to work anymore:
Using Flutter 3.3.1, Dart 2.18.0 (I had this problem with 3.0.* too) and
|
The above solution was inserted after another piece of code:
And apparently, it was not executed. I move it back on top and now it works as before. |
My problem was having SQLCipher and MLKit for some reason. This Podfile snippet helped, but I also had to remove conflicting package that had MLKit -> run -> and then return the package. I have no idea why this helped, but it solved it for me. I also had a test project and verified that this is indeed making a difference. |
We are using an encrypted database but I found that when using a long encryption key it is possible to find other combinations that will decrypt the database.
Db key =
3d80ac84-6dff-40bb-b803-abeed6c5e297
3d80ac84-6dff-40bb-b803-abeed6c5e297
+test
-> ✅test
+3d80ac84-6dff-40bb-b803-abeed6c5e297
+test
-> ❌test
+3d80ac84-6dff-40bb-b803-abeed6c5e297
-> ❌3d80ac84-6dff-4
-> ❌3d80ac84-6dff-40
-> ✅It seems that the max lenght for the encryption pragma key is 16. Other chars will be ignored. If this is intended behaviour this should be documented somewhere
The text was updated successfully, but these errors were encountered: