I'm developing an app where the user can use it in remote locations. I've created a startup dialog asking for password. I saved the password in SharedPreferences.
My question is, is it a good idea to do that? Or is there a better way for storing passwords for offline apps?
Because when I try to clear the data of my app in settings -> apps, my saved password in SharedPreferencesis also being deleted.
you can hash your password and store it in a file
search for hash function like MD5 or ..
Basically clear data of your app is cleaning what you store in SharedPreferences so that is normal. Store data in with SharedPreferences is usefull but someone with a rooted devices can access to these datas (basically an xml file store in "/data/data/app_packages").
Then you seriously have to consider to encrypt your password before to store it with SharedPreferences.
My question is, is it a good idea to do that?
Generally, it is not a good idea to store passwords in plaintext,
even if it is an offline application and gets cleared sometimes anyway.
Like you mentioned before, all that Information and even the database can be extracted from your Applicatoin Storage when the device is rooted.
Even If the content of that application is trivial, someone can do what mentioned above, just to see what password you use, so he/she can try to hack other accounts of yours..
This is especially the case if more people are using this application.
If you are aware of, and OK with that, you surely can use SP or DB.
If you want to do something in the right direction, you can encrypt passwords,
or hash them (though I recommend not to use MD5, but something like SHA2,Whirlpool,RipeMD2 or even PBKDF2).
Using an encrypted Database like SQLCipher is also nice, since you have to set it up only once, and everything that is added in to your application
afterwards is automatically stored encrypted.
If your only concern is that you dont want to the passwords be deleted, well, if you don't have Server communication, you have to live with that risk :)
Related
I'm trying understand which is the best way to store sensitive data in Android. In my app i want to insert a classic in-app-purchase model with some coins. My problem is that i'm not sure how to implement this correctly.
The initial idea was to simply use my firebase database, store the number of coins for every user and fetch the data every time the app is launched. This way I can easily detect some inappropriate usage but my users are forced to use the internet to play.
Looking at the documentations, I found this. Can this be a solution? Can I save in the internal storage the number of coins, maybe with some type of encryption, to avoid root user to modify the file? Then when the internet is on I can double-check the local stored variable with the the one in the database.
Thanks
Not an "easy" task.
Technically, you can create a SecretKey and encrypt data, so no normal user will be able to reproduce. If your concern are root users, You are kind of out of luck, as he can hook into your app while it is reading/writing that value.
But to store it online is not a solution in itself. You have to answer questions like: "Do you trust any server input"?
"How to make sure just paid coins are added"?
Have you had a look at Google Play billing?
it provides safe way's to determine if somebody paid or not.
This will require to be online.
If you have a sensitive data to save you can use sqlcipher database .. the good with it that it encrypt the database file itself so even the root user be able to get the database file he will not be able to decrypt it if you use a secured encryption algorithm.
you can find more about sqlcipher here
https://www.zetetic.net/sqlcipher/sqlcipher-for-android/
Since I assume you will grant your app a reading permission of your sensitive data and all writing processes should be reserved server-side, I would not recommend storing the data in a file on a phone, though every encryption can potentially be passed.
Maybe you already have heard about SharedPreferences, which is a good solution for let's say Preferences the user selects and that only shall affect his particular installation of your app. The difference is, that values are not stored in an external file, so not that easy accessible, BUT your app needs to write them, due only the app can access them directly (also your server can't). I am not aware of how your sensitive data is used at all but I would also not use SharedPreferences since it's injective-prone.
Official docs about SharedPreferences.
If security of your data (speaking of Confidentiality, Integrity, Authentication) is your No. 1 priority, simply don't store your sensitive data on the users device. Focus more on creating an API that ensures secure and performant passing of the relevant bits of your sensitive data. Hope this helps to give you a view of which way to go and which to walk around.
I am building an app which generates a random password and you can keep it along with your other details such as username, website url, name etc.
Basically a password management thing.
Things to be stored:
When I am clicking on the save button, I wanted it to be saved somewhere locally. So that, I could retrieve them and display it in another activity.
Can I share those things in SharedPreferences for all those password entries securely? [By password entry, I meant the entire class ]
I have referred to something like ComplexPreferences [ http://blog.nkdroidsolutions.com/class-object-in-sharedpreferences/ ]
I've tried them because I had created a class containing all these data [title, url, username, password, notes]. But I cannot retrieve them properly using a recyclerview. I'm ending up with some error.
If it cannot be done with SharedPreferences, how can I do it with SQLite Database?
But how can I save them securely? I don't know much about security in Android.
Please guide.
The shared preferences and sqlite db both are secure for an extend only.
It can be easily accessanle and can be modified even there are several apps available to edit the shared preferences and sqlite db in playstore . **
So i prefer not to store it locally
.you can use some kind of **algorithms and mechanisms to encrypt and decrypt the data that you are going to store locally.
if the device is rooted then its a SERIOUS ISSUE
Let's say, that you have a generated password along with other details like user name. Storing this kind of data is a perfect fit for SQLite. But, storing in plain text is not safe. Either the whole database or individual records should be encrypted. The former can be done using one of the open source database encryption libraries. For the later you have a couple of options:
Ask the user for a password each time he opens the app. Generate the actual encryption key using password-based encryption and the same salt value.
You can use the Android Keystore Provider to generate an encryption key and save it for you in a safe location on the device. Later, you retrieve the entry from the keystore and use it to encrypt/decrypt your database records using javax.crypto.Cipher.
Both options ensure that the encryption key is not be present in the app.
I still don't understand, why you need to save it locally? If only your application will be able to unlock data. In this case, only your application will have keys to working with this files.
For this example, you can easily work with SharedPreference with Private Mode. Furthermore, it's enough for most tasks. We using this option to save User's token, and it's Ok, for system. (If we talk about safety of this way, so you will have some risk for custom ROM, for Users, which manually flashed on device.)
If you need more complicated things, you can use sample, for using Android Keystore, with generating Key Pair, and saving data. For example you can check this source.
UPDATE!
So question was updated a lot, from first version. I will update information what you a looking for. Saving huge encrypted information locally.
Maybe easer way to do it, it's just use local encryption of data, as I described above, using Android KeyStore, KeyChain (links above). You will create our own KeyPair and will use for encryption and descryption some data. But this data, you will save in your DB in encrypted view.
Another more complex solution, will be creation of mechansim for encyption/decryption DB. As you described, you will save all information in DB, and after, just encrypt/decrypt you DB files. Fortunatly, we already have such library SQLCipher, just take a look. Fore example, this is pretty simple tutorial
I have been creating an app in Android recently, which has a login page. It's fully offline, so online or network-based solutions would not help me. I think there are two approach for me to accomplish this task.
Saving password hash in the preferences XML file
Saving password hash in the SQLite database
However, in my opinion both of these ways could be insecure because an user could load my app's data directory in a DDMS and then take out my preferences or database file and subsequently try to manipulate it.
Now, my question is:
Is there any fully secure approach (preferably not using files) or way to encrypt preference or database file?
Thanks in advance
SOLUTION (idea from Marcin Orlowski)
A relatively secure solution would be hashing password along with another string, which is only known to my app (with assumption of no resereve engineering), with this conditions, the attack could not replace my hashed string with his own hashed string.
No, there's no bullet proof solution. What's in the app can be extracted with more or less efforts or your app can be hacked/etc. If you need to store password, do not store plain as plain text. Do sha1 or md5 hash of it first and store the hash, so even if one would get hands on your prefs/DB then he still does not know the password (but he can try to brute force it using i.e. rainbow tables etc). Depending on sensivity of data you protect with password, using hash may be sufficient (if you do not encrypt data itself, then it makes no sense to go further)
Save the password hash in the private ContentProvider. SharedPreferences XML and Database file can only be get from DDMS if user uses rooted phone.
I don't understand what the hacker can see and cannot see when he enters in a mobile app, for example android. He decompiles the .apk, then sees some .class files. If for example, I encrypt a key/value pair in a file, I still need to call this key from the code, and if the hacker can see the code, no matter if the key is encrypted, he will know which key I am calling?
My goal is to keep some encrypted string in my app, for example the twitter account Id of my app.
Some topics talk about " a private key to read, what was encrypted with a public key ", but if I use them, I still need to store them somewhere in my app...
Don't completely understand your requirement but the rule-of-thumb is always assume that client is not to be trusted.
You have to ensure that
All decryption should be done in your server (which you trust).
The client should never be able to access the decrypted data (unless you want it to). Hence whatever part of your code that needs to directly access the decrypted data should be in the server.
The client should have only the encrypted data (if it must store data).
The client should not be able to access the private key you used to encrypt the data.
If in your case your client must be able to access the critical data directly, then your only resort is to use obfuscation techniques (Basically hiding your data/code, to make it hard to find/understand). Of course all obfuscation techniques can be defeated eventually by a determined hacker. You have to decide how valuable your data is, what are the probabilities a hacker will try and access your data.
To take an extreme example : storing your twitter account and password using obfusucation is very bad. Storing a twitter-url- might not be so bad.
you can get your keys from server while launching app. and also dont manage in app purchase detail in sharedPrefrence or Sqlite. because in rooted device user can see that data file from root browser or sqlite editor application so user be able to change value.
A very determined person can crack it, but it's a major pain to crack encrypted strings and will stop most hackers. Especially if you obfuscate your code with something like ProGuard.
Answer to a similar question for details on how to encrypt
I have an encrypted db with the "sqlcipher library", but now I don't know where I can store the db passwrod in the correct way, inside the app.
I think that SharedPreferences, in PRIVATE_MODE, is a good place to store it; but I'm not sure.
Any suggestion?
Thanks.
Even if you were to hide the password within the app itself, it can still be decompiled and found out. There is no where safe on a device with root. Your best bet would to have the db on a web-server and have the data retrieved from the server. That is the only way to keep a database safe from users (if the server is setup and secure).
I don't know where I can store the db passwrod in the correct way
The "correct way" is for the password to be inside the user's head, as the only reason to use SQLCipher for Android is to allow the user to defend the user's data.
You appear to be attempting to use SQLCipher for Android as a DRM mechanism, which will not work. There is no place for you to store a password "inside the app" that users cannot get to, given sufficient interest in doing so.
Depends on how paranoid you want to be. That will work if the device isn't rooted. If it is rooted, there's nowhere safe on the device.