4

I just noticed this article about a mobile app that is storing user information in plaintext. I've paid attention to the idea of storing the user's password on the server (using a SHA-512 hash function), but I'm not clear on the best methods for storage of personal information at the device itself.

Let me be clear I am essentially only talking about user names and passwords. The data that my app interacts with is not at all sensitive, and I know that I can implement some sort of symmetric encryption/decryption on that data.

For user convenience purposes, I'd like to offer the user an option to store their user name and password locally so that they aren't required to enter it each time they use the app. But I know that user's tend to reuse the same password for many different purposes, which means that I need to take precautions to keep my user's passwords secure. Classic tension between convenience and security.

Is it just simply a terrible idea to ever store this information locally? Or are there relatively simple means to securely encrypt this? Do the iOS and Android O/S provide any help with this?

Not necessarily looking for exhaustive answers, but I'd really appreciate some topics to research, article links, books, etc. Thank you very much. If this is a redundant question, please direct me to any posts that give answers that are still considered current.

Thank you very much!

AndroidDev
  • 20,466
  • 42
  • 148
  • 239

2 Answers2

2

All data on the device is automatically encrypted by the device to some degree, using the device id as the key. This prevents data from easily being read by anything other than the device itself, or someone with the device id anyway.

There's another level of encryption that you can pile on that utilizes the passcode, called Data Protection, which prevents the data being read unless the passcode is entered.

You can manually enable data protection in your app by using NSFileManager to access files and setting the NSFileProtectionKey attribute to NSFileProtectionComplete. See: Implementing and Testing iOS data protection.

Note that the user must set their device to require a passcode, and the stronger the passcode, the more secure the data will be.

You may be able to easily enable data protection through the provisioning profile for your app, even if you don't use the NSFileManager class with NSFileProtectionComplete. See: Data Protection / NSFileProtectionComplete - successfully supported through entitlements.plist?

I still wouldn't store the password. Store a randomly generated session key that is created when they log in. At least you can expire those and it's not the plain text password.

Community
  • 1
  • 1
Marcus Adams
  • 53,009
  • 9
  • 91
  • 143
0

Just a follow up to this post from a year ago. What I decided to do was to generate a random session key (similar to @Marcus Adams suggestion) but use that value as a salt. I then concatenate that session key with the user's chosen plaintext password and store this value on the device (if the user elects to store their password). i.e, the device stores this value:

device_hash = sha256(device_salt || plaintext)

That hashed value then becomes the string that I pass over HTTP to the server for validation. On the server side, I have a different salt value stored over there. When the server receives the device hash value, it has its own salt value which it concatenates to that string, and then performs its own hash. That final hash is the password that is stored in the server database. i.e., the server stores this string:

server_hash = sha256(server_salt || device_hash))

I think that this is a viable balance between security and convenience, particularly since I am only trying to protect the password, and not trying to encrypt the actual data that gets exchanged in the normal course of the app. If the user's device is compromised, no attacker can use a rainbow table or anything like that to reverse engineer the password since it is salted. SHA256 along with the long length of the password should eliminate a brute force attack if someone were truly motivated.

Curious if anyone has any criticisms of this approach.

AndroidDev
  • 20,466
  • 42
  • 148
  • 239
  • Why not use PBKDF2 instead of sha256(device_salt || plaintext). Additionally one can use the calibration function `CCCalibratePBKDF` to obtain the number of rounds. Also HMAC is a better choice than just concatenating a salt with the plaintext and hashing. – zaph Jan 10 '15 at 03:00