How can I encrypt CoreData contents on an iPhone
Asked Answered
K

9

55

I have some information I'd like to store statically encrypted on an iPhone application. I'm new to iPhone development, some I'm not terribly familiar with CoreData and how it integrates with the views. I have the data as JSON, though I can easily put it into a SQLITE3 database or any other backing data format. I'll take whatever is easiest (a) to encrypt and (b) to integrate with the iPhone view layer.

The user will need to enter the password to decrypt the data each time the app is launched. The purpose of the encryption is to keep the data from being accessible if the user loses the phone.

For speed reasons, I would prefer to encrypt and decrypt the entire file at once rather than encrypting each individual field in each row of the database.

Note: this isn't the same idea as Question 929744, in which the purpose is to keep the user from messing with or seeing the data. The data should be perfectly transparent when in use.

Also note: I'm willing to use SQLCipher to store the data, but would prefer to use things that already exist on the iPhone/CoreData framework rather than go through the lengthy build/integration process involved.

Kippie answered 29/10, 2009 at 16:39 Comment(0)
P
81

You can encrypt individual properties in your Core Data model entities by making them transformable properties, then creating an NSValueTransformer subclass which will encrypt and decrypt the data for that property. While this is not the whole-database decryption that you're looking for, it will have a much lower memory footprint than decrypting an entire database into memory. Additionally, it will allow the decryption to be done lazily, rather than all up front, so your application will load much faster. Depending on the encryption used, I would even expect that the on-disk data accesses for loading each entity would be slower than the decryption process for the properties, so you won't see that much of a performance penalty when accessing the properties.

Transformable properties like this are very easy to use, because you read and write to them as normal, while the encryption / decryption goes on behind the scenes.

Pathe answered 29/10, 2009 at 21:18 Comment(5)
I'm perfectly happy to do lazy, individual decryptions instead of one massive one if that's (a) easier and (b) faster.Kippie
How much are you trying to decrypt? Putting everything decrypted into memory may not be feasible, depending on the constraints of the device model. Also, if you have a large chunk of data, can the user sit there and wait while this is decrypted in full? Brad's design approach is definitely more transparent (i.e., amenable to troubleshooting) and will probably be more flexible when your model changes. It would probably be faster to only do the decryptions and Core Data fault lookups that are necessary, as opposed to fetching and decrypting everything at once. Profiling will tell you for sure.Parallel
Yes, but note that with symmetric cyphers and short attributes it starts to be really insecure.Monitorial
@Brad Larson, how would you recommend caching the decrypted values in memory to avoid decrypting them with each fetch request ?Privacy
Will it be possible to perform search oparation on core data if every property is transformable property ?Murrelet
L
9

Do you need to encrypt? Newer iPhones (3Gs, 4, iPad...) encrypt all data on the device. With a single, hashed, salted password on your app, no one can get to the data without a password. Data is sandboxed from all other apps.

Data Protection on iOS

Lanark answered 18/5, 2011 at 17:51 Comment(5)
This is the correct answer. There is no need to do this manually; see nickharris.wordpress.com/2010/07/14/…Zworykin
If the user does not have a passcode set on the device, the data will be available to others in a way that may not be acceptable for the application.Katydid
This is not the correct answer. This method is to protect user data from being exploited. There is a flaw in the system tools, which is they do not protect our (publisher) data. To do this, developers need to manually do it.Sigmoid
Foe example when You download an App in Itunes, in .IPA file there is ALL the SQLite backend. So you can grab it, before installing on a "secure" device.Mechanician
In a world without Jailbreak this answer would be correct oneAnnelleannemarie
R
8

"The purpose of the encryption is to keep the data from being accessible if the user loses the phone."

iOS has had Data Protection since iOS 4, and Core Data has supported this for a long time. Data protection is designed for exactly the kinds of scenarios you are interested in. By default, Core Data NSSQLiteStoreType files have NSFileProtectionCompleteUntilFirstUserAuthentication for applications built with the iOS 5 API or later. The WWDC 2012 session Protecting the User's Data goes into this topic in much more detail, and recommends using NSFileProtectionComplete. You can use this with Core Data by passing that value in the options dictionary used to open your Core Data NSSQLiteStoreType store.

Example:

NSDictionary *storeOptions = @{ NSPersistentStoreFileProtectionKey : NSFileProtectionComplete };
if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self storeURL] options:storeOptions error:&error]){

The broader topic of device security is covered in iOS Device Security

Rioux answered 13/9, 2014 at 6:57 Comment(3)
As I understand it, this will encrypt the SQLite files when they are not in use, but when the Core Database is open, the SQLite files are not encrypted. Is that correct?Coming
@Coming yes you are right. And these setting only apply if there is a passcode on the device to begin with.Colony
There are more purposes to encryption than just that. For eg. as an app developer... I want to keep users (that is including the device owner) from seeing the contents of their database.Brittenybrittingham
S
5

I am currently using https://github.com/project-imas/encrypted-core-data to encrypt my coredata store. It is a custom implementation of NSIncrementalStore basically is a community replacement for apple's own persistent store that has an encryption option. It is a drop-in solution that works. You can also take the sqlite file out and decrypt it with whatever passcode you choose in many different clients.

The implementation does not have 100% coverage and doesn't allow for some features such as subquery predicates. I am due to submit my first PR to the repo to hope change that soon ;-). I almost have it completley working with a very complex coredata app. It also has the added benefit of allowing you direct SQLite access without having to worry about apple's implementation changing on you since you have full access to the source.

Southerner answered 18/7, 2014 at 4:42 Comment(2)
We too are testing with the same encrypted-core-data class. How do you handle migrations with it though? Especially progressive migrations?Juster
encrypted-core-data does no longer seems to be maintained, the last commit was made in 2017 github.com/project-imas/encrypted-core-data/graphs/…, and the docs state that it's "is known to work successfully on iOS versions 6.0 through 9.2." Does anyone know of a maintained project that serves the same function?Isaacson
G
4

I succeeded in adapting Apple's CustomAtomicStoreSubclass example code for use in a Mac desktop application, resulting in an encrypted NSBinaryStore-style persistent store written as a single file in the filesystem. My approach:

  • Copy the CustomAtomicStoreSubclass & CustomAtomicStoreSubclassCacheNode class source code into my project and rename them
  • Store the key and initial vector in the Keychain
  • Use the OpenSSL library bundled with Mac OS X
  • Encrypt NSKeyedArchiver output and write the ciphertext to disc (decryption is the reverse)

I intercepted backing store reads & writes in the readFile, metadataForPersistentStoreWithURL:error:, setMetadata:forPersistentStoreWithURL:error:, and save: methods in CustomAtomicStoreSubclass.

The Subclassing Notes for the iPhone's NSAtomicStore Class Reference looks similar to that of Mac OS X's. Perhaps this approach might also work with the iPhone.

Gangling answered 29/4, 2010 at 14:54 Comment(1)
Sounds like an interesting approach. I'll give it a shot.Kippie
B
4

I know this is an old question, but it's still quite relevant and I recently had to tackle the subject myself.

Transformable properties are a potential solution, but did not seem to work with NSPredicates, which is a big drawback. I did not pursue the CustomAtomicStoreSubclass approach, but am curious if others have had success with it.

My concerns were similar to those of the original poster, and I ultimately wound up doing the following:

  1. Decrypt the store to a temp file
  2. Load the decrypted store normally
  3. Migrate the store to an in-memory store
  4. Delete the unencrypted store

In my case, my store was read-only, but this could be expanded to write the store back out, encrypt it, and delete the unencrypted store once more. You can also always skip #3 if you have a large store and/or aren't concerned about having an unencrypted file sitting around while your app is running.

The Core Data file I was working with was ~1MB, and could be encrypted/decrypted very quickly.

Burkhard answered 10/11, 2010 at 0:44 Comment(1)
What happens if an attacker kills your application when you are migrating the store to the in-memory store? He will have a copy of your data.Monitorial
P
0

How do I encrypt or decrypt data?

"The Certificate, Key, and Trust Services API provides functions for generating symmetric and asymmetric encryption keys, creating and verifying digital signatures, and encrypting keys and nonces. The CommonCrypto library is used for symmetric encryption, hashing, and HMAC operations. Refer to Certificate, Key, and Trust Services Reference and the CC_crypto(3cc) man pages for for more information."

Parallel answered 29/10, 2009 at 20:59 Comment(1)
This is not an answer to the question "How to cipher Data Base in iOS"Lippi
M
0

You can use Trasformables, and I confirm, you cannot use them with predicates, but (and it's worse) you cannot even use

... = [self primitiveValueForKey:@"crypted_data"];

if You use predicates..

it works fine if You crypt you data using:

[self setPrimitiveValue:cryptedPsw forKey:@"crypted_data"];

to crypt data. (and for example on the simulator.... and move on the project bundle later..)

Mechanician answered 11/8, 2013 at 20:26 Comment(0)
E
-4

Encryption is encryption no matter what format your data is in, and you certainly don't need to worry about how anything "integrates with the views." All you have to do is decrypt it before you try to read anything meaningful.

Extraterrestrial answered 29/10, 2009 at 17:13 Comment(1)
Let me try to clarify: there are lots of ways to encrypt and decrypt data. I want to know what fits best in the iPhone universe. What has the lowest friction?Kippie

© 2022 - 2024 — McMap. All rights reserved.