Securing data using Core Data in iOS Securing data using Core Data in iOS sqlite sqlite

Securing data using Core Data in iOS


Since iOS 5, Core Data persistent stores have used Data Protection to encrypt data by default. From the iOS 5 release notes:

For apps built for iOS 5.0 or later, persistent stores now store data by default in an encrypted format on disk. The default protection level prevents access to the data until after the user unlocks the device for the first time. You can change the protection level by assigning a custom value to the NSPersistentStoreFileProtectionKey key when configuring your persistent stores. For additional information about the data protection that are new in iOS 5.0, see “Data Protection Improvements.”

This is also covered in the WWDC 2011 session "What's new in Core Data".

As a best practices usernames and passwords should be stored in the keychain. If you are storing a username and password for a remote service (such as an HTTP server, FTP server, etc.) it's preferable to use the keychain through the NSURLCredentialStorage API.


The "encrypted-core-data" project has limitations for average to complex data models. In my iOS app, we had some many-to-many relations, and some one-to-many relations between certain entities.

The bridge code (code that bridges core data to SQLCihper) has lackings such as it doesn't have the NSOrderedSet implementation. Modifying the bridge code was a high cost effort for us.

So, we decided to encrypt the sensitive data in the column instead. Thus for that we used the core data native capability of transformable attributes, and use crypto library to encrypt an entity's attribute. This capability encrypts the data when it goes to the column, and decrypts it when it is read. This is done automatically.

This leads us to performance issues then, when we query data over multiple rows to show in on a list view. To go about this issue, we then restore the column type to the normal string type, and then do the encryption and decryption manually in the code, but only when required. We also use a transient attribute in the model to store decrypted form. This help us in restoring the performance to the acceptable level.

I am still looking for a better way to encrypt whole database while using core data.


You can use something like encrypted-core-data which is a Core Data accessor wrapper around SQLite Cipher.

This is a subclass of NSIncrementalStore which interacts with an encrypted database.

If you're just storing passwords then the keychain is a better option, but if you want to encrypt the Core Data store then the above is the better option.