Note: This post's primary purpose is to help me think through this problem. I have no prescribed solution at the end of it. The conversation will continue on Stack Overflow. I will update this post once I have a final approach.
Realm has a great write up and sample code for encrypting your database. This documentation and sample work as intended, until you try to decrypt realm when:
- A user has a password on their phone
- The device is locked
- Your app is trying to do work with Realm when a remote notification comes in
This happens because we can't access the keychain to get (or create) the key to en/decrypt the Realm. The default kSecAttrAccessible
value is kSecAttrAccessibleWhenUnlocked
There are a few options as I see them:
- Change
kSecAttrAccessible
tokSecAttrAccessibleAlways
. I don't like this because it's a) too open and b) it was slated to be deprecated in iOS 9 - Change
kSecAttrAccessible
tokSecAttrAccessibleAfterFirstUnlock
orkSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
. This is better but still feels too open to me, even though the docs state: This is recommended for items that need to be accessed by background applications - Create a second, non-encrypted Realm to use as a staging database. Store notification data here, then when the app wakes up from user interaction (the device would be unlocked), move the data from the staging Realm into the encrypted real one. This doesn't feel right either, as we'll have data temporarily not encrypted
- Combine 2 and 3 and encrypt the staging Realm, and protect it's key with
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
- ??
I'm currently trying to decide if #2, if #3 is worth putting the time into, or if I can come up with a #5