I have an Android App where a user enters some sensitive information in the form of text. I need to store this data on a remote server, to be retrieved by that user from a different device. I want to secure this data against everyone other than that user, especially a rogue database admin - the user should be the only one capable of recovering the information.
My approach is, SALT will be generate in Android app and every sensitive data will be hashed with this SALT and will be stored for later decryption to get the actual raw data.
Is this the correct approach? or Any better approach for this?
If yes,
What if the user change the device?
How to use the same SALT in the new device as SALT cannot be saved in database?
Update: Sensitive data needs to be stored in Firebase Database.
Disclaimer
I'm not a security professional. I'm not an expert. I'm just some random developer on the internet who's done some reading in the past and took a stab at answering your question. Head over to the information security stackexchange if you want more reliable information.
A user enters sensitive information into your program. You want them to be able to recover it later, so you must save it somewhere. How to handle this?
Where to save it?
On the device if it doesn't need to be accessible from elsewhere.
On a server if the user might need to access it from a different device (or recover it).
How to secure it?
Encrypt it.
What to encrypt it with?
A standard, secure algorithm (such as AES), and a key derived from a user provided password.
But users tend to come up with poor passwords. If we're sending this to a server, and the database might be compromised, how to protect against brute force attacks?
Employ a key stretching algorithm, such as PBKDF2.
How secure is this, really?
Well if the user picks a poor password, and then your database is compromised, brute force will be relatively easy.
If the password ever leaves their device (like if you, say, reused the same password for the app to log in to your servers or something) then you're treading in dangerous waters.
Related
My mobile app has users, so after someone log in, I send back the user id to be used for future requests (GET and POST HTTP web service calls to manage user data), and I store it in an sqlite table called user_settings after encrypting it using jbcrypt along with the salt. is this a safe way to do it?
You could use sqlcipher to encrypt the database with a randomly-generated key, created on first startup, that you store in the Android Keystore System.
As #njzk2 said, there is no way to absolutely protect this data. Encrypting the database with a random, unique key, and stashing that key in the keystore, will make things much more difficult for an attacker, even with physical access to the device. In this scenario, the goal is not to keep the attacker from ever accessing the password, but slowing the attacker down enough that the user can change their password before the attacker can use it.
Does anyone knows what is the most secure way to store sensitive information in application? Because using internal storage and shared preferences is vulnerable if person who want that information have a rooted phone.
Case is that I have some kind of activation code which needs to be stored somewhere inside the phone (not on server) for further communication and authentication with server side, that code needs to be secured and not available to other apps and users, even on a rooted phone. Also, user can not be bothered with additional verification (he enters the PIN code when he enters the application and send that code to the server side for authentication) .
Bottom line, is there a secure way to store something and to be secure that it will remain hidden, even on a rooted phone?
Unfortunately the commenters are correct. There is no way to guarantee with 100% security that the activation code can't be hacked. Microsoft has spent millions of dollars on this, and there are still pirated copies of Windows out there, because at the end of the day you have no control of the code on the client. If you endow the client with the ability to decrypt or otherwise access this stored authentication code (without needing to go to the server), then someone can reverse engineer the app to undo your protection. This is true even if you retrieve a decrypt key from the server.
The best way to do this depends on your use case, but here are some ideas:
Have the client submit the "activation code" to the server, where you can blacklist it if you think it's stolen. This is how Windows works. This is the only option you have if you want to use an activation code and not bother the user.
Have the user register an account and have the app resubmit the user's credentials each time it runs. This way you have a user account to deactivate if you suspect piracy.
Have the server provide the decrypt key. This does not guarantee that the activation code stays safe, but it does up the bar for potential reverse engineers.
Drop the whole DRM idea completely, and focus your attention on making a good product. Studies that music companies have shown that dropping the DRM makes no difference in the number of people who buy your product.
I'm developing a video game for Android. It will be an online game, which would save user's statistics, achievement, objects, etc. in the local SQLite database.
Thinking about the security... I read that a user can edit all his/her databases saved in a rooted Android device. I would not want the user to be able to edit the database of the game.
So, what can I do? Is there any option to make the DB really secure? Password? Encryption?
Thanks
A determined attacker can get at any data on the device. If you're encrypting data on the device before putting it in the database, then you have to have keys on the device and a determined attacker can get at any keys that are stored in the devices memory or persisted.
The only way encryption would help is if neither the encryption nor the decryption happens on the untrusted device -- merely the storage. You can encrypt the sensitive data on a machine you trust, storing the encrypted bits in the database for later decrypting by a machine you trust.
You can't use a password to secure this either. Passwords stored in the device memory or persisted on the device can be read as easily as private encryption keys.
If you don't care whether the user reads data from the DB, but don't want them to be able to write data, you could have critical data signed by a trusted machine before being stored. Then if the device connects to a trusted machine, it can check the signature to verify that that critical data has not been tampered with.
EDIT:
You can't trust any computation performed on an untrusted device unless you're willing to go to fairly extraordinary lengths -- the only thing you can do is verify data routed through an untrusted system via signatures, and prevent eavesdropping by an untrusted system on data passing through it via encryption.
If there's nothing online, I'm not sure what you can do. You can make it more difficult, but I'd say its unlikely to be absolutely secure. I think what I'd do is take a snapshop of the db at a checkpoint, and send that off to the server, and (basically) check that the data hasn't been changed by a user. If the hashes don't look right, you can cripple the account (or whatever).
I wouldn't get too crazy, though, unless you have a serious game.
SQLite data encryption is possible, for more detail see this.
This may also help.
Ive been working on multiplayer android game that sends locally stored data to a server every minute. Then I find out that locally stored data is not secure. I could encrypt the data, but how effective will that be? The whole game is based on updating the server with user data. What should I do? My last resort would be to have everything take place on the server-side. Sorry for the choppy sentences.
You cannot trust the client. You can't trust any data stored on the client.
You can trust that people will try to hack your game.
So, just go ahead and do it server side.
Much will depend on what you are protecting. If you want to protect against cheating by your user, then, first, place a value on this cheating. If you pay money to winners, then no security on client will protect you.However, if it is just some game score, it may not worth the effort to break encryption and disassemble the application. So simple encyption may be sufficient.
Different story if you are trying to protect user data if device gets in wrong hands. Again, start with placing a value on that data. Ideally, you can just ask user for password every time app starts. Then you can use password based encryption to get the rest of information. Or you can calculate password hash and send it to server.
I haven't been able to find a way to open a password-protected SQLite database on Android. Since the device can easily be rooted, I am thinking of password protecting the database file. However, I am not having much luck finding anything built into the Android platform.
I don't think that Android framework supports password protection on databases. Your best bet is to encrypt your data. See SO question: Android Sqlite Password Encryption
You can encrypt SQLiteDatabases. Android does not support full-database encryption so you'd have to implement that yourself if you want to.
If you want to go down the encryption route, you're much better off just encrypting the sensitive information yourself and storing it in a database field, as per Morrison's answer.
All that said -- where are you putting the password for the encryption function? You'll probably need it somewhere in your application! In which case someone can just disassemble your code and then find the password, and decrypt the info (although it will be a bit more work).
Unless you're hashing info (one-way) then without hardware encryption on a device (and even that has flaws) you cannot store anything on the device perfectly securely -- you're always going to need to decrypt the info some time and for that the password has to be on the device somewhere.
If you want really robust security then store sensitive information on a server (preferably in a really secure location), not the device, and only communicate between the device and server over encrypted channels (HTTPS). You'll also need to authenticate the device in a secure manner. But to do that you need to store some sensitive information ON the device in order to authenticate the device with the server, unless you force the user to enter a password every time (recommended if security is a must).
If the information is stored on a server you can't necessarily prevent someone who shouldn't gaining access (by finding the password you have stored or phishing the user if it's stored in their head), but you can revoke access to the information.