Encrypt and decrypt with custom PINs
Closed this issue · 8 comments
Hi David,
thanks for this great project, I'm using it in my App and it's works great.
I'm not sure that this is the right place where ask you this.
Now I've to encrypt/decrypt my values with a pin provided by the user every time he wants to access to data. So, I have no need a random key saved in Keychain but I have to pass the pin at the EncryptionManager.
How can I achieve this?
P.S. My entities are user info, and I have a different PIN for each user.
My idea is to use PBKDF2 over user's pin like you suggested me. But I don't understand how pass the pin at the EncriptionManager because it is created and managed behind the scene by the Core Data framework (so, I don't create it explicitily). Could you explain me in more detail how I have to change the key
method? Sorry but I'm a bit confused.
Thanks for your help,
Giorgio
@giofid I would modify the code here to go find your user's PIN, run it through PBKDF#2, and return it. The rest of the code should function as normal.
Do note, the above will only work for a new install and will stop working if a user changes their PIN. If you already have users using the application what you need to do (in order to not compromise existing data) is a little more complicated:
To preserve the existing key:
- Get the user's PIN
- Run PIN through PBKDF#2
- Use the result to symmetrically encrypt the secret key.
To get encrypted data:
- Get the user's PIN
- Run PIN through PBKDF#2
- Use the result to decrypt the secret key
- Return secret key in this method to decrypt data
That should allow you to have key management that shouldn't break when you upgrade the app. Additionally, when a user changes their PIN, you only need to re-encrypt the secret key, not all of the data separately.
Final note: a 4-digit PIN only has 10,000 combinations. It would be trivial to brute-force. I would suggest using an alphanumeric password.
@DavidBenko thank you very much. Now I know what I need to do.
The only thing that still don' t understand is how the key
method "finds" user's PIN.
Try to explain you in more detail my UX. During the registration, the user enters a username, the PIN (or ,better, a alphanumeric password, like you suggested) and other fields; then, when the Save button is pressed I want to save this info via Core Data and your library (by using password entered). The key
method is called by transformedValue
method that is called, behind the scenes, by Core Data framework. I see no way to pass the password down in this chain. Any suggestions?
Thanks for your time,
Giorgio
@giofid If the PIN is local to the device, I would store it in the keychain, and in the key
method, fetch it from the keychain. I definitely would not store the PIN in plain text in core data.
My problems come from this: I prefer don't save PIN anywhere. It's entered by the user each time, so I don't need to save it.
I'm thinking to add a class method to EncryptionTransformer
class to set the current PIN. But it appears to me a horrible solution. The only?
@giofid So you aren't checking that the PIN is valid anywhere? (by PIN, I kinda meant hash of the PIN used for auth).
You could make a singleton that stores the PIN in-memory after the user enters it, and you can retrieve it in the key
method and when wipe the ivar when it's no longer needed? Other than that, I'm not sure your use-case works well with what I've written
Closing because I don't think there's much more I can add to this issue.