5

I've read up on various Q&A here on how to manage encryption of a local SQLite database on iOS, and from what I've seen, pretty much everyone agrees that it's bad, BAD idea to store the encryption key in code. So, I decided to not do that.

Now, another, more secure option I liked is to send the encryption key from the server over TLS, and use certificate pinning to help prevent people from MITM'ing. Unfortunately, this creates issues for my situation, since the app I'm building needs to be fully functional without an Internet connection.

A third option I have not seen is a more elaborate method of security through obscurity (i.e., more obscure than hiding the password in plain text in the app). Here are a few options I've been entertaining (but all feel somewhat questionable to me):

  1. Use an unknown, but unguessable value (such as the elapsed time for a certain API request to finish, or the coordinates the user taps on a screen) to derive the key.
  2. Have the user of the app enter a distinct passphrase when data is first downloaded, and derive the key from that.

I know that best practices dictate deleting the derived key (I was planning on using PBKDF2) and keeping the salt + number of rounds around. However, I don't want to ask the user for the password phrase more than once (long story short, they will only provide it after they "authenticate" their device, which only needs to happen one time).

As a result, I think I'd need to store the key locally, in plain text (or in the keychain, but what would that really do?) OR store the password phrase (from 1 or 2 above), salt, and rounds. The app would then manipulate the password phrase before feeding it into the key derivation function. This seems far preferable, since storing the derived key totally undoes all security.

So, what I want to know. Is this dumb? Will someone determined be able to reverse engineer this in an afternoon? Or would it be difficult to figure out how the app is manipulating the key before feeding it into the key derivation function?

  • there are several native protected storage options available for iOS that work pretty well; i'm not an iOS dev so i don't know the specifics beyond a chart in a defcon talk, but i can tell you that "storing a key locally" is no longer necessarily a categorical auto-fail. – dandavis Aug 17 '16 at 23:20
3
+50

Put it in the keychain. This is exactly what it's there for. What it does, is to encrypt the keys when they're not being used by your app, and to limit access to them to your app alone.

Simply have the application securely generate a new random key on first use, and store in the keychain for re-use on subsequent launches of the application. This way you're using systems designed for these purposes, every device has a unique, high-entropy key, and you're not limited by the inherent weaknesses of password-bases systems or the pitfalls of roll-your-own-key-storage mechanisms.

  • Someone with physical access to the device can access the content of the keychain, doesn't he ? – Nate Aug 23 '16 at 17:22
  • @Nate Only if the device is unlocked. It's not a fail-safe option, of course, but nothing is. It's an easy to use mechanism that protects well against the most likely threats, which is generally better than you'll get from a hand-rolled alternative. – Xander Aug 23 '16 at 17:27
  • Anyway, if the device is not unlocked, the hard-drive is encrypted on iOS devices. – Nate Aug 23 '16 at 17:34
  • 2
    This is the right answer. If you need an offline, non-reauthenticated-each-time option, the keychain is by far your best option. You won't prevent the local user from accessing it, but pretty much nothing will. By having it generated and put into the keychain, you ensure that each database uses a separate key - much better than a hardcoded one. – crovers Aug 29 '16 at 16:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.