Cannot open encrypted database with SQLCipher 4

Using CocoaPods, SQLCipher 4.0, Swift 4. Database created and encrypted(with SQLCipher 4) by DB Browser for SQLite.

SQLCipher 4 works well with database without encryption, but it fails to open an encrypted database. It shows error message: Error setting key: not an error, Error retrieiving cipher_version: no more rows available

Code:
rc = sqlite3_key(enneaDB, myKey, Int32(myKey.utf8CString.count))

The above operations always work well with SQLCipher 3 in other Apps.

Edited:
When App running on iOS 10 simulator, App crashes with this error message:
dyld: Symbol not found: _sqlite3_key
Expected in: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 10.0.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libsqlite3.dylib

Any help? Thanks.

Hi @jdleung

A few questions + suggestions:

  1. Are you including any other dependencies/pods that may be including SQLite?
  2. Can you verify that you are in fact using SQLCipher by seeing what’s returned from PRAGMA cipher_version; ?
  3. Can you provide your Podfile and/or a sample project that reproduces the issue?
  4. Can you provide a sample database (with no sensitive information) that reproduces the issue?
  5. What build/version of DB Browser for SQLite are you using?
  6. If you create the database within your swift code rather than using DB Browser for SQLite does the issue still exist?

Hi @mmoore

  1. There is no other dependencies/pods including SQLite.

  2. The cipher_version: “unknown error” on iOS 10, I have not tested on other iOS version

  3. Here is the Podfile:
    platform :ios, ‘10.0’

     target 'Enea' do
         pod 'Charts'
         pod 'RetroProgress'
         pod 'Google-Mobile-Ads-SDK'
         pod 'SQLCipher', '~>4.0'
     
         use_frameworks!
         pod 'YYText'
         pod 'BTNavigationDropdownMenu'
     end
    
  4. I will upload it tomorrow later.

  5. DB Browser for SQLite version is 3.11.2 Based on SQLCipher 4.1.0

  6. I’ll try to do this later, but can it create an encrypted database without sqlite3_key working?

Thanks.

@jdleung

This is the culprit. If you look at their pod spec, they are linking sqlite3.

If both SQLCipher and a standard version of SQLite are linked, this can lead to undefined behavior.

Our recommendation would be to remove any other pods that depend on SQLite.

Alternatively, there is some guidance in these posts on how to ensure SQLCipher is preferred when linking:

Note: This is considered unsupported

Specifically in your scenario, since you’re using cocoa pods with use_frameworks you’ll want to put this as the first item in your target’s Build Settings > Other Linker Flags: -framework SQLCipher as recommended in the second post. We’d also recommend following the guidance in that second post related to ensuring that SQLCipher is properly linked at runtime.

Hello, @mmoore

It works like a magic after removing Google Ads from CocoaPods.

And then I added Google Ads again in Podfile, and inserted -framework SQLCipher in Project > Other Linker Flags, Both SQLCipher and Google Ads work perfect.

Thank you so much!

@jdleung

Glad it’s working well for you now.

@mmoore awesome solution! I can’t believe this subtle problem has costed hours to locate.

My problem was very similar, by using Google library (again) at cocoapod. It secretly induced a sqlite library dependency which cause mislink at runtime. These kind of runtime linking issue is again very subtle and extremely hard to be troubleshooted. Especially when the problem is not noticed right away.

While @sjlombardo has written a comprehensive article about this issue. Although it is rare to meet, I suggest it should be put at FAQ or common mistake section to avoid fellows from suffering if they are so lucky to meet this problem.

Anyway, appropriate the good work.

1 Like

@micyat

Thanks for the recommendation. We’ve added a note below the integration options on the iOS Tutorial page here: https://www.zetetic.net/sqlcipher/ios-tutorial/ with additional details and linking to the article.