2

I have a private API key in my Android app that is used in certain areas -- is there no way to prevent a user from somehow reverse-engineering or decompiling the Java to see what that key is? Is it not safe to put the key as a static field in a class? Is it safer to put it as a string resource in strings.xml? Or something else entirely? Or is it simply not possible to prevent a sufficiently motivated user from finding it?

KaliMa
  • 1,970
  • 6
  • 26
  • 51
  • 3
    this one: *it simply not possible to prevent a sufficiently motivated user from finding it* ... you may still obfuscate is somehow so it will not be avaible right after decompilation – Selvin Jun 16 '17 at 14:13
  • 1
    Possible duplicate of [Hiding strings in Obfuscated code](https://stackoverflow.com/questions/4427238/hiding-strings-in-obfuscated-code) and [look here](https://stackoverflow.com/questions/22949801/simple-hiding-obfuscation-of-strings-in-apk) too – Pavneet_Singh Jun 16 '17 at 14:15
  • 1
    @Pavneet_Singh: Good find. – T.J. Crowder Jun 16 '17 at 14:16
  • if you using proguard then you can put it as String, proguard can protect your API key at a level. – Aniruddh Parihar Jun 16 '17 at 14:16
  • @T.J.Crowder thank you for appreciation , just learning from great members like yourself – Pavneet_Singh Jun 16 '17 at 14:19

2 Answers2

3

Not only can it be, it's not even hard.

You can make it harder by not storing it as a string at all, but as a series of numbers that you convert to a string at runtime (perhaps obfuscating it somehow).

But the answer to

Or is it simply not possible to prevent a sufficiently motivated user from finding it?

is: Right, it's simply not possible.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Can you elaborate a bit more with the "series of numbers" example? I am okay with adding a few layers of protection even if it doesn't stop the most determined. I'd rather just not be low-hanging fruit. – KaliMa Jun 16 '17 at 14:45
  • @KaliMa: Well, that particular example probably would be fairly low-hanging. For instance, suppose your string were `"bqzT"`. You could store that as `int a1 = 0x5348e823; int b1 = 0x902b77b2; int c1 = 0xaff50d8b; int d1 = 0x2bf6eacc; int a2 = 0x5348e841; int b2 = 0x902b77c3; int c2 = 0xaff50df1; int d2 = 0x2bf6ea98;` and reconstitute it with `String s = new String(new char[] { (char)(a1 ^ a2), (char)(b1 ^ b2), (char)(c1 ^ c2), (char)(d1 ^ d2) });` Again: That's not particularly hard for someone to figure out, but the string won't be cleartext in your class file. :-) – T.J. Crowder Jun 16 '17 at 16:24
  • So you define `a1` arbitrarily and then xor it with character `b` to get `int a2`? – KaliMa Jun 16 '17 at 17:11
  • @KaliMa: Yup. (I did it the other way around, but with xor it comes out the same either way. :-) ) – T.J. Crowder Jun 16 '17 at 17:28
-1

It is best to include your String as a constant in a class file and obfuscating it with String obfuscation and various other techniques using some free or commercial obfuscator. It's the best you can do and you will be fairly save. You can double-check yourself by decompiling and trying to find the key as if you didn't know it. You will see how good your protection is then.

BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • 1
    Have you ever come across [Schneier's Law](https://www.schneier.com/blog/archives/2011/04/schneiers_law.html)? Not being able to recover your own secret tells you nothing about whether others can. – Andy Turner Jun 16 '17 at 14:23
  • @AndyTurner: If you go through the obvious attacks and it looks hopeless you did a decent job at least. Of course it's not possible to guarantee nobody will ever succeed but some obfuscators are pretty brilliant at messing up decompiler outputs and the likes – BullyWiiPlaza Jun 16 '17 at 14:25
  • Best hope those baddies stick to only using obvious attacks! – Andy Turner Jun 16 '17 at 14:30