I have an iOS project currently facing a problem. The database used in it seems to be encrypted at present, but the database file cannot be decrypted using SQLCipher. The following phenomena are provided:
Happend on iOS 14.4.1 (iOS 15.X is another case, the database is not encrypted, I won’t discuss it here.)
cipher_version is null and sqlite_version=3.32.3
If the project is added pod ‘OpenSSL-Universal’, the version will change to cipher_version=4.5.0 and sqlite_version=3.36.0, but still failed to open the database.
Additional information, under the exact same XCode configuration, iOS 11, 12, and 15 are unencrypted(plaintext DB), while iOS 13 and 14 are encrypted but cannot be opened. Because the unencrypted ones can be re-encrypted successfully, so the first thing is to solve the database that cannot be decrypted.
I think the database was encrypted incorrectly before. I don’t know how it was encrypted before, but it should be that SQLCipher was not used successfully. Is there a way to make him use the correct SQLCipher encryption again?
Hello @chtsai - Some versions of iOS shipped an undocumented encryption feature in the system SQLite library. We originally identified this behavior in iOS 13 and 14. The encryption function does not use SQLCipher, but it does respond to PRAGMA key. As far as we can tell, this undocumented encryption feature was removed sometime after iOS 15.0, likely because it was not intended for application use.
Coming back to SQLCipher, unfortunately if the database is not encrypted using SQLCipher, the library doesn’t know how to open it and can’t convert or re-encrypt it. Unfortunately, you may need to remove the database and recreate from scratch in that case.
Hi @sjlombardo , thanks for your reply. We have explored the reasons and found that -lsqlite was used in the project settings, resulting in the use of wrong SQLlite encryption. At present, we will solve the problem by rebuilding the database, but the data will be lost.
It seems that sometimes some third-party libraries are referenced through the CocoaPods, and the XCode setting will automatically add the -lsqlite setting. If the developer does not pay attention, it may lead to unexpected encryption results.
In our case, we provide a framework for integration with other APPs, and the framework will use SQLCipher for database related operations(with CocoaPods), but we cannot confirm the project environment on the APP side. Is there a correct way to use it to ensure that the project uses SQLCipher correctly for database encryption?
We usually advise that applications using SQLCipher via dynamic linking perform a runtime check to verify that the expected library is being used. Executing the PRAGMA cipher_version statement provides a simple way for an application to do this. SQLCipher will report its version and build type, which can be checked before use of the library. If a non-SQLCipher library is loaded instead the statement will return an empty result set, and the application can fail safely. There is an example of this logic on the integration page.