问题
I have a question about Core Data encryption. I'm storing some sensitive user data in a Core Data SQLite database. The critical values are all transformables and I'm using AES256 to encrypt and decrypt them 'on the fly', including an individual IV for every value. The encryption key is the SHA512 hash of the password the user has chosen. This works very well so far.
Now about the user password. When the user launches the app he is asked for his password. The password is being hashed with SHA512 and stored in the iOS keychain. For every write or read operation the NSValueTransformer will get the password from the keychain. If the app is being closed, I delete the password hash from the keychain.
In my Core Data database I have a special entity which has a random number != 0 as it's only value. To test if the user has entered the correct password I fetch this entity and read the number. If it is =! 0, I know that the password was correct because when the decryption fails the NSValueTransformer always returns 0.
Now my actual questions: Would you consider this a good approach on encryption? How else would you test if the entered password is correct?
I'm a little concerned that storing the password hash in the keychain while the app is running makes everything slower, because the NSValueTransformer has to access the keychain all the time. Would it be sufficiently secure to just keep the password hash in memory, so it'll be deleted when the app closes?
回答1:
You shouldn't use the hash of the password, hashes are designed to be fast so it's (comparatively) easy to do a brute-force attack. Use a key derivation function like PBKDF2.
Don't use a key directly derived from the password as an encryption key. If the user changes the password, you need to reencrypt all data and backups become worthless. Use a randomly generated encryption key that you encrypt with a key encryption key based on the password.
I'm not so sure about storing the hash in the keychain instead of just holding it in memory. The last time I looked into this, it was comparetively easy to decrypt the keychain. And every attacker that can read the memory of your running app will most likely be able to snoop on the keychain access or the decrypted data. Just keep it in memory and make sure to wipe the memory if the app suspends into background etc. This holds obviously also true for every piece of decrypted data.
[EDIT: @JeffLockhart to clarify the procedure for a master encryption key] you generate a random key to encrypt your data, let's call it key A. You could use SecRandomCopyBytes to generate key A, see Apple's CryptoExcercise for a usage example. You use key A to encrypt the user data. To save key A, you have to encrypt key A with a second key B. You shouldn't use the password directly as key B, because of fast brute-force or dictionary attacks. So you derive a key from the password with a PBKDF, like in this stackoverflow answer. You then encrypt key A with key B, e.g. using CCCrypt. You save the encrypted key A and the salt used to derive key B it. To decrypt, the user enters the password, you derive key B using the password and the salt. You decrypt key A using the derived key B. Hope that clarifies.
回答2:
You could have a look at this:
Secure Incremental Store
They have implemented a NSIncrementalStore subclass which is using an encrypted SQLite-Database. This is a drop-in replacement for Apple's SQLite Store. Comes with a price tag as well.
来源:https://stackoverflow.com/questions/14905135/core-data-encryption