I am using SQLCipher for Android. I have done all the necessary things that are needed for
loading the libs as mentioned in http://sqlcipher.net/sqlcipher-for-android/
I observed that you set the password i.e the key in :
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(databaseFile, "test123", null);
Then how is your password safe from a hacker? As it can be accessed from a java file. ?
Is there any correct way where i can store the password ?
Thanks,
Nibs
Then how is your password safe from a hacker?
It's not. Hard-coding a passphrase makes for simple demonstrations, though.
Is there any correct way where i can store the password ?
The user should supply the passphrase for the user's database via your UI. The user then stores the passphrase in the user's head, or perhaps you combine what's in the user's head with something else for lightweight two-factor authentication (e.g., MAC address of paired Bluetooth wearable).
I would like to suggest the following approach:
The first time you create the database you have to create a random password.
You store this password in the Keystore.
Whenever you open the app you read the password from the keystore and use it for connecting to the database.
So how does the keystore access work? See blog entry 1 and blog entry 2 and the corresponding github repository. The solution is available for Android version 2.1 to 4.3.
Big caveats:
The solution works only with private API access, so it might break in the future.
A screen lock password is required to store keys and all keys are wiped if a user removes his lock screen password.
What is being overlooked is the fact that the demonstration given by SQLCipher is purely for demonstration . It is up to the imagination of the developer to overcome the obvious. Slightly less obvious is that you would NOT store the key in a private local variable, since performing a strings search against your class files could reveal your key, reducing the dictionary necessary in a successful brute force attack. Open your classes.dex in a hex editor and try it.
It isn't the .java files you should be concerned with, as only your developers should be in there. It's the .class files. The next level of effort is some effort of obfuscation, but that really only limits the impatient.
Take a look at this discussion
https://groups.google.com/forum/#!topic/sqlcipher/OkE0rUwXEb8
Related
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'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 :)
I need to store sensitive data in a sqlite database in an android app.
How can I be sure this data is very safe?
I know I can encrypt the data using a key, but where do I store that key? I don't want to ask the user to fill in a key either, I just want it to work on it's own.
Because I am afraid of reverse engineering I don't want to put an encryption key in the code either.
I found out about SQLCipher. It says it's a very secure way of encrypting the data in the database, but why is it that way? Don't I also need to keep a key to unlock that information? Or is this really a perfect way of making sure the data is safe?
And if it isn't, what is an (almost) fail-proof way of storing sensitive data in an sqlite database?
You said...
I don't want to ask the user to fill in a key either, I just want it
to work on it's own. Because I am afraid of reverse engineering I
don't want to put an encryption key in the code either.
Unfortunately, you need to do one of these things (well, probably). You can ask the user for a password and then derive a key from that using an algorithm designed for that purpose (that's known as Password Based Encryption - PBE - and Android includes some good PBE algorithms standard). You could store the key in your code or as a resource within your APK, but then someone would be able to reverse engineer it. You can do so and obfuscate your code, which will slow down the reverse engineering process, but you cannot make it impossible (your code will need to determine the key at some point so it's just a matter of an attacker figuring out how it is doing it).
Other approaches that have been tried here include forcing your client to connect back to a server to retrieve the key over the network...but then what happens if network connectivity is interrupted and what prevents the server from giving the key out to anyone, like an attacker? Well, then you could use mutually-authenticated SSL to ensure only your client is allowed to get it...but then you need to store the client-side SSL private key...which is exactly the same problem you have now. :)
So...the bottom line is that you need a key (or something equivalent) to encrypt/decrypt the data. You can store it and make it harder for someone to reverse engineer it. You can inconvenience the user and make them type in a password. But...you need that secret knowledge somehow.
Symmetric cryptography requires a key to encrypt and the same key to decrypt. There is no way around it.
Do not store the key in the code because it can be decompiled (Like you've said).
Ask the user for a password on the first use and use PBKDF2 to derive a cryptographically secure key to use in the encryption.
Either the user has to enter the password or you need to store it in the memory. What I'd do is, ask the user to specify a duration where the key will be cached in the memory to use for decryption.
And if the duration is expired, the user WILL have to enter the password again.
I didn't check SQLCipher thoroughly but it says it uses AES-256. AES is a symmetric cryptographic algorithm and it needs a key to encrypt and the same key to decrypt.
Is it possible to let apps auto gen a random password? May be gen from place,time or others information this will no need to ask user's pass.
What would be the best most secure way to handle confidential text in an Android app?
The basic structure is (text/int) and some similar variations of it.
The app only shows a selection of the (readable text /readable int) at a time, so decryption will only be done for very few pairs at a time.
I need to make sure that extracting the complete (text/int) information is practically impossible - if possible :-)
Is there any standard library/scheme to handle this?
Many thanks
EDIT (after getting some very interesting responses to this question):
It seems that even when the data is encrypted one could easily take the de-compiled code from the app, combine this with a self-written extraction routine, and hereby get all the decrypted info to a file. Since the encryption key has to be provided to users of the app, everybody could potentially get to the data this way.
So in summary there is no real good solution?
You can save your text/int pair into the SharedPreference.
Because it's not secure, you can encryt the data before saving it into the SharedPreference in the same way as Google do in the Application Licensing package.
More details can be found in the Implementing an Obfuscator part.
The code source of the AESObfuscator can be found in the SDK in the market_licensing/library/src/com/android/vending/licensing folder.
I think in your application you can use a symmetric cryptography and you can store your key in the Keystore. This key should be protected with password. Every time, when you run your application, it will ask the user for the password. If the password is correct then the key is extracted from the Keystore and used to decrypt your data. In this case, there is no difference where you store your data (text/int pairs) because all data will be encrypted. For Android SDK look at the package java.security and to the class java.security.KeyStore
If you want to supply your application with the data that you don't want to be extracted then obfuscation is a possible solution if you write in Java. If you want this functionality to be written in C/C++ then use Android NDK.