drift
drift copied to clipboard
SQLCipher: iOS Encryption
Describe the bug
I have setup encrypted drift database with packages below. I cannot go higher version because of web dependency issues with other packages.
drift: ^2.18.0
sqlcipher_flutter_libs: ^0.6.0
# drift_flutter: ^0.2.0
# TODO: Update below when web is updated
sqlite3:
I am using below to setup SQL Cipher
Future<void> setupSqlCipher() async {
try {
await applyWorkaroundToOpenSqlCipherOnOldAndroidVersions();
} catch (e) {
if (kDebugMode) {
print('Error applying workaround for old Android versions: $e');
}
rethrow; // Re-throw to ensure the caller is aware of the error
}
try {
open
..overrideFor(OperatingSystem.android, openCipherOnAndroid)
..overrideFor(
OperatingSystem.linux, () => DynamicLibrary.open('libsqlcipher.so'))
..overrideFor(
OperatingSystem.windows, () => DynamicLibrary.open('sqlcipher.dll'));
} catch (e) {
if (kDebugMode) {
print('Error during SQLCipher setup: $e');
}
rethrow; // Re-throw to ensure the caller is aware of the error
}
}
but am continually getting error as below in IOS emulator device. Document mentions no need to setup anything for iOS so am not sure what is missing here. Any help is appreciated. Android does not have this issue.
[ERROR:flutter/runtime/dart_isolate.cc(1315)] Unhandled exception:
Unsupported operation: This database needs to run with SQLCipher, but that library is not available!
#0 openAppDatabase.<anonymous closure>.<anonymous closure> (********/application/database/database.dart:217:15)
database.dart:217
#1 Sqlite3Delegate._initializeDatabase (package:drift/src/sqlite3/database.dart:105:13)
database.dart:105
#2 Sqlite3Delegate.open (package:drift/src/sqlite3/database.dart:82:9)
database.dart:82
#3 DelegatedDatabase.ensureOpen.<anonymous closure> (package:drift/src/runtime/executor/helpers/engines.dart:431:22)
Do you have a dependency on drift_flutter? That depends on sqlite3_flutter_libs, which is incompatible with sqlcipher_flutter_libs :(
~[IOS] This database needs to run with SQLCipher, but that library is not available~ Drift_flutter with SQLCipher
UPDATE ON BELOW: Interestingly, when I tested on real device, iOS database PRAGMA returned the cipher and iOS was also encrypted. But when i run app in iOS emulator, cipher is not found and encryption does not work. Any hints?
Thanks @simolus3 for your reply.
I have done some more testing.
This issue occurs only on iOS. Encryption works in MacOS, and Android. For iOS, assert(_debugCheckHasCipher(rawDb)); keep on failing that cipher not found in iOS. I have below versions. If i disable assert(_debugCheckHasCipher(rawDb)) i get unencrypted ios database.
I tried to do what is mentioned in this link https://github.com/simolus3/sqlite3.dart/tree/master/sqlcipher_flutter_libs#incompatibilities-with-sqlite3-on-ios-and-macos as adding -framework SQLCipher in "Other Linker Flags" but no luck.
drift: ^2.18.0 (i have dependency override to 2.20.2)
sqlcipher_flutter_libs: ^0.6.4
# drift_flutter: ^0.2.0
sqlite3:
After open database and I am running a query like below in database. With this query, for MacOS and Android, i get encryption enabled, but for iOS not. Any suggestions or recommendations from your side on what I can do more for iOS?
// Check if database is encrypted or not
Future<int> _isDatabaseEncrypted(MyEncryptedAppDatabase database) async {
try {
// Execute PRAGMA command to check the cipher version
final result =
await database.executor.runSelect('PRAGMA cipher_version;', []);
// Check if the result is not empty and contains a cipher version
if (result.isNotEmpty) {
final cipherVersion = result.first.values.first
.toString(); // Convert to String to use isNotEmpty
debugPrint('constructDb: PRAGMA cipher_version result: $cipherVersion');
if (cipherVersion.isNotEmpty) {
debugPrint(
'constructDb: Database is encrypted with cipher version: $cipherVersion, return 1');
return 1; // Return 1 if encrypted
} else {
debugPrint(
'constructDb: Database is not encrypted: cipher version is empty, return 0');
return 0; // Return 0 if not encrypted
}
} else {
debugPrint(
'constructDb: Database is not encrypted: PRAGMA cipher_version returned no results, return 0');
return 0; // Return 0 if not encrypted
}
} catch (e) {
debugPrint(
'constructDb: Error checking database encryption status: $e, return 2');
return 2; // Return 2 if an error occurs or status is not known
}
}
I also encountered the same problem
@dkliss Have you found a solution to the problem?
We had the very same problem, but the -framework SQLCipher in Other Linker Flags fixed it for us (as described here). You have to make sure though that it is set as the very first linker flag. Order matters here. Also note that this "fix" is apparently considered unsupported.
@Fabian-G Thank you so much. As you suggested, adding the -framework SQLCipher configuration to the Other Linker Flags in Xcode and ensuring that -framework SQLCipher is placed at the top resolved the issue.