I retrieve data from an external server for use with my android application. I would like this data to be only accessible with my app. I use a standard http connection to get the data from apache/php server in json format. I also send some params to the server to retrieve relevant data. Now, what I'm planning to do is:
- Send the params
- Send something like md5("someSecretPhrase"+params).
- Check if the secret phrase is correct on the server side.
Now, the question is - is it a safe approach regarding the reverse engineering? For now I can think of no other possibility to get this data. But if someone is able to decompile my apk, he will be also able to retrieve this "someSecretPhrase" (rather hard to do on the server side) and then access the server, isn't he? Is it a real threat? Is there any other possibility to authenticate my app by the server?
I looked at the forums eg. Identify whether HTTP requests from Android App or not? and then respond appropriately, but they don't explain the decompilation problem.
One of basic rules of security is: you don't trust client data. Ever.
You should consider your app decompiled, all "secret" keys known to attacker, etc.
You can, however, hinder attacker's attempts to forge your requests. Sending (and verifying) checksum of your request is one of methods (your idea of MD5(secret_key + params)
).
You could also switch to a binary encrypted protocol. But this requires MUCH more work and quite a different architecture of server.
Have your application perform a handshake with the server, so the algorithm isn't just a string, but a whole process. Use Sessions/databases to track your handshake
You can hide your links by set all url links and paramete names in strings.xml for example:
http://wwww.yourdomain.com/yourpage.any
user_name
and get url such at :
String serverUrl = Resources.getsystem().getstring(R.strings.name_your_link_id);
String parameterKey = Resources.getsystem().getstring(R.strings.name_your_parameter_id);
Uri url = Uri.parse(serverUrl+"?"+parameterKey+"=" + yorusername);
and make any http request
HttpURLConnection con = (HttpURLConnection) url.openConnection();
when any one try to decompiled your app he will show only id as long integer in R.java file get code such this
String serverUrl = Resources.getsystem().getstring(12346546564);
String parameterKey = Resources.getsystem().getstring(123321321132);
Android requires that one should sign their app(signing authority or self signed) before it can be installed. We can utilize this to check whether requests are coming from your app or not.
- Sign your app with your certificate.
- Find the certificates signature and save it in your backend server.
- For every request, expect this signature to be sent by the app.
- validate the signature sent by the app at server level and accept only if they matches.
Even in that case where someone tampers with your app, he has to sign it again before it can be installed, which would change the apps signature and our validation mechanism would simple reject all such requests.
This answer is based on this blog. Use https for app<->server communication.
Unfortunately if someone decompiles your apk, then it can easily see your strings.
EDIT: I don't think there is a better way to do this.. maybe only to publish your application on android market with the android Copy Protection turned On...