Araw
Araw

Reputation: 2478

Storing data locally on device

I'm making an application where users can store data on the device. I was thinking about using database storage. But I've been reading somewhere that it is possible to manipulate data that is stored locally on the device. So what would be the best way to avoid such "attack" on the data? I have been thinking about encrypting each field in the database, but again then I have to store an encryption key on the device as well(?), which again I guess can be located? So does anyone have any other ideas/improvent of my thoughts?

Thanks for any help!

Upvotes: 2

Views: 1372

Answers (2)

zapl
zapl

Reputation: 63945

I'm looking for a way to make it a big challenge

Challenge accepted :)

The first thing you should do is to store the data in your app directory since it is not readable for the user / other apps on a regular device. Links to app data con be obtained from Context e.g. Context.html#getDir(). The directories you get from Environment are public.

That prevents average users from getting the data. But a lot of people have rooted devices and can access the data without problems, so that is still pretty insecure.

To make it a lot harder you'll need encryption. Any strong encryption that is not fundamentally broken like WEP will do. Using encryption you force the user to find the key (and encryption method) since the encrypted data can't be decrypted in reasonable time.

That leads to the problem of having a secret key somewhere available to your app but not the user. And this is the part where you need to get creative since there is no secure way to do that.

The simplest way is to put the key in plaintext in your app code. Like private static final String SECRET = "42". By simply having encrypted files you will already stop most users from digging further since at that point you need some programming skills to read the data.

If the user has those skills he will likely start to look at the code of your app (using e.g. dex2jar + jd-gui). You should do the same if you want to know how hard it is to reverse engineer your app.

Understanding the code / finding the encryption method + password will get harder if you use proguard to obfuscate the code because app internal class-, method- and variable names will be shortened to A.B.c(d) like code. But method calls to Android's API can't be renamed since you would need to rename the methods on the device. Also string constants like "42" won't be changed.

The next step of making it harder is to replace that constant by something dynamically generated by your code. The basic example below for example builds the password by dividing numbers by two. The advantage when using this approach is that the password is no longer stored in plaintext and you need to understand / reverse engineer the method that converts the data into the password.

private static final byte[] password = {8, 4};
private String getPassword(byte[] data) {
    StringBuilder sb = new StringBuilder();
    for (byte b : data) {
        sb.append(String.valueof(b / 2));
    }
    return sb.toString();
}
// returns "42" if I did not make a mistake

The next vulnerable point is that calls to device crypto APIs can be easily located (since they can't be renamed) which makes it a lot easier to figure out where to look for the encryption. If you don't want to write your own crypto method which I would strongly suggest you don't because a slight error in here may corrupt data or break the complete encryption.

That problem can be hardened if you use reflection for example (calling methods by supplying the name of the method / class supplied in a String). That String can as well be obfuscated like above example did with the password.

If you do all that and don't use a method not as simple as this one you can make it really hard. dexguard for example can do that for you but it's not free and has the problem that the same method is used for many apps and a lot more people will try to break that than your custom method.

Finding a good method to hide information in your app that is used to generate a key and a method to hide the key generation & encryption / decryption is best figured out by yourself so the method itself is not public knowledge.

You can use combine a lot of techniques to hide the information like moving parts of that into native code so Java guys like me have a hard time or use a network connection to let your server do some work.

But in the end it's all Security through obscurity and all the extra security measures don't benefit the user but require extra processing time & additional app size.

Upvotes: 4

CommonsWare
CommonsWare

Reputation: 1006539

So what would be the best way to avoid such "attack" on the data?

Do not put it on the device.

I want to make the data secure against the user of the app.

Then do not put it on the device. It is the user's device and the user's bandwidth, and hence it is the user's data.

But I'm looking for a way to make it a big challenge if the user finds out he/she will try to do so.

Simply using a database or something else on internal storage will stop 99% of Android device users from accessing your data. There is nothing you can do to stop the remaining 1%.

Upvotes: 2

Related Questions