There is a lot of discussion going on how to store credentials on the Android platform. What I’m going to discuss is focused on the Android platform, but you’ll notice that most of the things can be applied to all mobile plattforms. There are some differences, e.g. that you should use the much more evolved secure keystore of the iOS. There will be a keychain in Android 4.0. But of course you can screw up the secure storage on all platforms or even examples of the vendor show you how to screw up.
Before you start storing credentials the most important question is:
- Do I really want to store that data and why?
Before you simply answer “yes”, consider the following:
- Do you want to authenticate the user inside the app to check if he is allowed to access the app and other data?
- Then use a secure cryptographic hash function (e.g. SHA-2). Use a salt which is long enough and randomly generated on the fly. You can store the salt in plain along with the generated hash. Use multiple hashing rounds (e.g. 10’000).
- Don’t forget to check in every Activity that the user is already authenticated, because Activities can be invoked directly.
- Do you want to authenticate the user against a server?
- Before I go back to how you should store the credentials: Please use a secure channel to the server. One possibility is to use SSL (e.g. a HTTPS connection), but make sure you check the server certificate. Another possibility is to include a public key and have the corresponding private key on the server (actually I like this version even better, because you don’t have to trust hackable CA root companies).
- Change the server side. Talk to your customer if you are developing an app for someone else, it’s not a big deal to change something on the server side. Try to store a session token instead of the password. Even increasing the expiry time for sessions is better than storing passwords on the client. Only increase it if the request is coming from the Android app, but not for all clients (like standard browser authentication).
- If your really can’t change the server side and you can not use a token, you have a problem. Whatever you are doing from now, you have to store the password in reversable form, but the client isn’t a good option for that. Attackers equipped with root exploits and reverse engineering skills will always be able to get that password from somewhere (most of the time from the code or the filesystem). Consider that people often reuse passwords, which is a bad habit and if the password for your application is extracted, there might be other services that have to suffer from the laziness of the user.
- There are several ways of how you could try to protect the credentials, but again, they’re all useless against a sophisticated attacker: E.g. encryption (key in the source code) and good obfuscation (some are just useless). EDIT: With the new Android KeyChain you are even better off if you have a hardware-backed storage on the device. Simply use the KeyChain to store a private key that you use to encrypt the password. The password can only be decrypted when the attacker is in the posession of the device, as he can not extract the private key from the device. Well of course he can extract the key, but root permissions are not sufficient and it means messing with the hardware (which is very expensive).
- At least tell the user how the credentials are stored, why it could be a problem and what they can do to be protected (e.g. disable “remember password”).
- Don’t screw up and write the password somewhere to the logs…