My app is now using Core Data (SQLite store) AND a separate SQLite database. My Core Data part is where my static schema is stored and the SQLite store is where my dynamic schema is stored. Tables in the database and columns in the tables can be added and deleted. That’s the dynamic part. I’m doing it this way for flexibility and performance reasons. So everything has been working great up until the next thing I need to do. Encryption.
I want to encrypt the SQLite database using SQLCipher. I’m using cocoapods to integrate SQLCipher with the following parameters in my Podfile:
target 'TFCoreMac' do
platform :osx, '12.0'
pod 'FMDB'
pod 'FMDB/SQLCipher'
end
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
if target.name == 'TFCoreMac'
target.build_configurations.each do |config|
config.build_settings['OTHER_CFLAGS'] ||= ['$(inherited)']
config.build_settings['OTHER_CFLAGS'] << '-DSQLITE_HAS_CODEC -DSQLITE_POWERSAFE_OVERWRITE=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_TEMP_STORE=2 -DSQLITE_THREADSAFE=2 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS4_UNICODE61'
end
end
end
end
The problem I’m having is the version of SQLite that my app seems to be using is the built-in system SQLite version that Core Data is using, which does not support encryption.
Is there a way to allow Core Data to do its own thing with SQLite while other parts of my app use the SQCipher version of SQLite? Or can I get Core Data to use the same SQLite build that SQLCipher is using?
Some ideas of what I can try would be very helpful and appreciated. Thanks.
Thank you for your interest in SQLCipher and for posting to the discussion forum.
One thing I noticed is that you’re using both the standard FMDB pod and the FMDB/SQLCipher pod, you should only need to use the FMDB/SQLCipher pod (which includes all the standard FMDB stuff + SQLCipher).
Is there a way to allow Core Data to do its own thing with SQLite while other parts of my app use the SQCipher version of SQLite? Or can I get Core Data to use the same SQLite build that SQLCipher is using?
We DO NOT SUPPORT using SQLCipher with a project that includes a separate sqlite3 dependency, including via CocoaPods. That sort of configuration carries multiple inherent risks, including undefined behavior, deadlocks, loss of data, loss of encryption functionality, etc.
That being said, you may want to review this document: Important Advisory: SQLCipher with Xcode 8 and new SDKs – specifically the section under Project Setup and Linking which has instructions to ensure SQLCipher is linked into your Application first.
Thanks for the help! That was the key! Adding the -framework SQLCipher entry to the Other Linker Flags setting at the project level.
Also thanks for the warning about using SQLite with another dependency. I’ll have to keep an eye on that. I know some people are using SQLCipher with Core Data in the Encrypted Core Data project. But that project hasn’t been updated in many years and I’m reluctant to rely on something old like that. That’s why I’m leaving my Core Data store unencrypted and SQLCipher will be used just to encrypt records data in a separate SQLite database file.
There is a minor version number difference between the Apple supplied SQLite (on Ventura). Ventura has 3.39.5 and SQLCipher has 3.39.4. Hopefully that’s just a minor difference and nothing consequential.
Actually it turns out just having that extra FMDB pod in my Podfile is what caused the built-in SQLite version to be used. The Other Linker Flags option didn’t make a difference as I took it out to test and with just having FMDB/SQLCipher in my Podfile allowed the SQLCipher version 3.39.4 to be loaded instead of the built-in 3.39.5.
But your warning does have me worried a bit. There are quite a few differences in the way the built-in SQLite is compiled vs. the SQLCipher cocoa pods version.
What was occurring since you were including both (FMDB + FMDB/SQLCipher pods) is that -l"sqlite3" was being automatically put in your Other Linker flags by the FMDB pod and -framework SQLCipher was after it (from the FMDB/SQLCipher pod) so standard sqlite was being linked first into your Application. After removing the standard FMDB, SQLCipher is now properly being linked first.