views:

1139

answers:

4

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.

A: 

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.

Azeem.Butt
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?
James A. Rosen
+1  A: 

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."

Alex Reynolds
+4  A: 

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.

Brad Larson
I'm perfectly happy to do lazy, individual decryptions instead of one massive one if that's (a) easier and (b) faster.
James A. Rosen
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.
Alex Reynolds
+1  A: 

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.

Ty
Sounds like an interesting approach. I'll give it a shot.
James A. Rosen