I have an android app with web service urls. If anyone decrypts my apk file, the webservice url will become visible.I am using HTTP POST for calling web service.
An
"URL" stands for Universal Resource Locator. The whole point of a URL is to access some kind of resource, and to do this, you obviously have to tell the network you are connecting to what it is you want to fetch.
Now if you are worried that a hacker can access your source code, then surely he can also hook up Wireshark or Fiddler and simply observe what connections your app is making, and what info you are passing along and receiving back.
Sorry, but I simply can't see any good way around this.
If you're worried about your server/services being hacked or DOS`ed, I think you had better focus on securing them as well as you can, rather than trying to hide them.
I use it this in all android application I developed
gradle.properties
API = http://ec2xxxxx.compute.amazonaws.com
API_KEY = $2c11SoL/NjJ28
create utils.gradle
utils.gradle
class Utils {
static def r = new Random(System.currentTimeMillis())
}
def String toJavaCodeString(String string) {
byte[] b = string.getBytes();
int c = b.length;
StringBuilder sb = new StringBuilder();
sb.append("(new Object() {");
sb.append("int t;");
sb.append("public String toString() {");
sb.append("byte[] buf = new byte[");
sb.append(c);
sb.append("];");
for (int i = 0; i < c; ++i) {
int t = Utils.r.nextInt();
int f = Utils.r.nextInt(24) + 1;
t = (t & ~(0xff << f)) | (b[i] << f);
sb.append("t = ");
sb.append(t);
sb.append(";");
sb.append("buf[");
sb.append(i);
sb.append("] = (byte) (t >>> ");
sb.append(f);
sb.append(");");
}
sb.append("return new String(buf);");
sb.append("}}.toString())");
return sb.toString();}
ext.toJavaCodeString = this.&toJavaCodeString
build.gradle
apply from: "utils.gradle"
android {
defaultConfig {
buildConfigField 'String', 'API', toJavaCodeString(API)
buildConfigField 'String', 'API_KEY', toJavaCodeString(API_KEY)
}}
and access your private url;
public static final String API = BuildConfig.API;
There is no way to protect "secret" information such as URLs embedded in an APK. A determined / motivated hacker can defeat any scheme you care to design ... if he / she has access to a platform where your app is being run.
In order for your app to run, the app running on the user's device needs to be able to decrypt the hidden URL. The user can either intercept the URL in decrypted form in the app's address space, or he / she can reverse engineer the algorithm and decryption key you are using to do the decryption.
Another "attack" is that your app needs to use the URL to make a request. That request can be intercepted on the users device before it is protected by the SSL / TLS channel to your (presumably) HTTPS enabled service.
And on top of that, if you embed a "secret" URL into an app and that secret is compromised and you have to turn off / relocate your server, then you are making problems for all (legitimate, paying, etc) users of your app. They won't be happy campers.
The correct approach is to make your service secure ... and use some kind of authentication mechanism so that hackers need more than just the URL to make requests. Users can / should be issued with individual credentials (e.g. auth keys), and you need to implement a way to invalidate a given users' credentials at the server end.
I have fixed this in two ways
Encrypted the URL in my code with my private key and on request call i decrypted it again,
public static String encryptIt(String value) {
try {
DESKeySpec keySpec = new DESKeySpec(new byte[]{105, 107, 18, 51, 114, 83, 51, 120, 121});
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);
byte[] clearText = value.getBytes("UTF8");
// Cipher is not thread safe
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, key);
// Log.d("aa", "Encrypted: " + value + " -> " + encrypedValue);
return Base64.encodeToString(cipher.doFinal(clearText), Base64.DEFAULT);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
and decript it by using this
public static String decryptIt(String value) {
try {
DESKeySpec keySpec = new DESKeySpec(new byte[]{105, 107, 18, 51, 114, 83, 51, 120, 121});//cryptoPass.getBytes("UTF8"));
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey key = keyFactory.generateSecret(keySpec);
byte[] encrypedPwdBytes = Base64.decode(value, Base64.DEFAULT);
// cipher is not thread safe
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decrypedValueBytes = (cipher.doFinal(encrypedPwdBytes));
// Log.d("aa", "Decrypted: " + value + " -> " + decrypedValue);
return new String(decrypedValueBytes);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
note in my case that the private key is new byte[]{105, 107, 18, 51, 114, 83, 51, 120, 121}
i think it was $ecrEt
or something like i forget it.
so if they decompile the APK they wan't be able to find the service link inside you code.
so the base url will be like this public static final String ROOT_API = "aHR0cHSC86LSy9tbS2JpuZW50aWtoYWAbGUJhdC5qbw==";
2- Also you have to add progaurd to your code
BUT, they can smurfing the netweok and find the url if the hacker is advance person, in this case you have to user SSl certificate "https" and make the webserivce POST.
hope you got my point.