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):
- 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.
- 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?