ccgus / fmdb

A Cocoa / Objective-C wrapper around SQLite
Other
13.84k stars 2.76k forks source link

FMDB w/SQLCipher and an App Clip #869

Open knightcode opened 4 months ago

knightcode commented 4 months ago

We're building an App Clip to accompany our main iOS app. The two apps need to share the encrypted sqlite db, so they both belong to the same App Group, and we create the db in a directory that is accessible to both (via FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: APP_GROUP)). The App Clip essentially creates the db, choosing the encryption key and setting up the schema. The full app then gets installed over the app clip so as not to delete any of the files, user defaults, or keychain entries. When the full app then loads, I can confirm that the db file is still there, the encryption is still in the keychain, but sqlite is throwing an error code 26 "file is not a database". We get the NSLog statements from lines 869-871 in FMDatabase.m.

SQLcipher is included via cocoapods and FMDB is included via the swift package manager.

Our code that interacts with FMDB and sqlcipher is common among both apps. The same methods are called by both apps to open the db and perform the initial queries.

The db is opened via the FMDatabaseQueue(url:) method.

The first query after opening the db is a "PRAGMA key = ...", which doesn't throw any errors, and we again confirmed the same key is passed for both apps.

It's the next query after this one that fails... as expected.

Oddly enough, we and our users experience similar behavior when getting a new iOS device where the new device is restored from a backup. We previously thought this was due to an artifact of a new apple device identifier interacting with our system, which is still a possibility. Finding the same behavior with the app clip, though, makes me wonder.

Everything works fine if the main app creates the db.

After installing the main app, I've listed the contents of the directory to see the sqlite db there. I confirmed the posix permissions and owners are the same. The file size oddly increases a bit after the install. The App Clip claimed it was 53248 bytes. The full app lists it at 65536 bytes.

I'm at a loss for what behavior could be causing this.

R4N commented 4 months ago

@knightcode

This is most likely an integration issue rather than a defect with either FMDB or SQLCipher. When using FMDB in conjunction with SQLCipher you'll want to use the FMDB/SQLCipher suspec rather than standalone FMDB with SQLCipher separately. Using SQLCipher with other libraries/frameworks which have a dependency on standard sqlite carries multiple inherent risks, including undefined behavior, deadlocks, loss of data, loss of encryption functionality, etc.

When using SQLCipher it is recommended that you check the result of the cipher_version PRAGMA to confirm that your application is actually using SQLCipher. There's an example of doing that with FMDB in my comment here: https://github.com/ccgus/fmdb/issues/821#issuecomment-811490793

knightcode commented 4 months ago

@R4N is that available through SPM? I have to downgrade to cocoapods? ... I was so close getting use of my xcconfig back :/

R4N commented 4 months ago

@knightcode

SQLCipher isn't available through SPM. There's discussion about that in this post: https://github.com/sqlcipher/sqlcipher/issues/371 which links over to the Swift forums which explains the blocker: https://forums.swift.org/t/plugin-generated-header-files-are-not-available-from-project/56875

knightcode commented 4 months ago

It's not that hard to wrap the headers in a framework. Do they just want to hold us hostage?

knightcode commented 4 months ago

@R4N I still don't see what's stopping you from publishing a properly linked framework as a swift package

R4N commented 4 months ago

@knightcode Please see me colleagues comment in the other thread linked in my earlier comment: https://github.com/sqlcipher/sqlcipher/issues/371#issuecomment-1360074443