9

I need to store a private string key inside of the app. Its value will never change and is set manually in code. I cannot obviously just store it as a String as reverse-engineering method would reveal it, even with obfuscation applied.

How do you suggest I protect this private key?

I though of saving it into a database, but a database can be pulled out of the phone as well.

PS. this key is a special parameter so an important method and it's crucial it stays unknown to anyone! It's not a decrypting key. This string will be used as a parameter to encryption method (md5 or similar) and then a result will be sent to our Internet service.

EDIT

Sorry, for making it so complicated. I thought I could get an answer with as few info as possible.

This app will allow users to send some text to an Internet service which then posts that text to a web site. We need to make sure that the text is sent via Android phone as any web robot script can mimic android phone and post a spam. As captcha-like methods are not welcome on mobile phones, there will be a secret key which will be put through md5 (with some other things) to generate a hash code. This hash will be sent to an Internet service. The Internet service will use the same key to get a md5 result and then compare it to see if the sender is a mobile phone or some robot.

This is really the max I am allowed to say. I hope it is enough.

AstroCB
  • 12,337
  • 20
  • 57
  • 73
sandalone
  • 41,141
  • 63
  • 222
  • 338
  • 7
    "it's crucial it stays unknown to anyone" If it's truly crucial, you can't include it in the application at all. Otherwise, an attacker could just step through your code with a debugger, stop at the point that your code uses the string, and inspect the contents. The attacker doesn't need to know how to decrypt the string, but only needs to install the Android dev tools in order to let your code do the decryption instead. – Adam Mihalcin Apr 18 '12 at 06:25
  • @AdamMihalcin No, this string will be used **for encryption** and then a result will be sent to some other Internet service. Does this change anything? – sandalone Apr 18 '12 at 06:35
  • I agree, if you use your string like a pswd/TAN or similar you may want to look into the way banks do it nowadays by sending a one-time-use code to the mobile and just use this - every time the user wants access he gets a new one. @Adam Mihalcin , what exactly do you mean? I understand that one may LOOK at the code, however, debugging a loaded app, how is this possible? – user387184 Apr 18 '12 at 06:37
  • @AdamMihalcin Edited the answer again. – sandalone Apr 18 '12 at 06:46
  • @user387184 Edited the answer again. – sandalone Apr 18 '12 at 06:46
  • Check out my answer on a similar question: [hiding strings in Obfuscated code](http://stackoverflow.com/questions/4427238/hiding-strings-in-obfuscated-code/39856033#39856033) – Efra Espada Nov 17 '16 at 16:52

2 Answers2

11

I'd suggest that you rethink your security architecture. Anything shipped with the app is discoverable. (For instance, Android's license validation library is designed so that a public key is shipped with the app.)

One possibility is for the app to retrieve the key from a server (over a secure socket or https connection). This would obviously require that the app submit to the server some sort of identification/validation (probably based on user input).

If you're using the key for encryption, then take another look at how public key encryption is supposed to work. Your app should have the public key; the internet service can then decrypt with the matching private key.

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
  • Hi Ted, I've edited the question. "This string will be used as a parameter to encryption method (md5 or similar) and then a result will be sent to our Internet service. " – sandalone Apr 18 '12 at 06:37
  • 2
    @sandalone - It sounds like you should be pulling the hashing key from the server. The user can enter credentials through the phone for the server to verify before issuing the key. You can get fancy about this: the hashing key can be based on a random number generated by the phone and submitted along with the credentials. – Ted Hopp Apr 18 '12 at 07:05
  • Yes, I've come up with a similar solution based on your suggestions. Thanks! – sandalone Apr 18 '12 at 07:37
4

If you can settle with @Adam's comment, there is at least one solution I know of for persisting a String value on the phone in a... well... persistent manner, meaning that the value will survive a uninstall/re-install of your app (a factory reset would remove it though), yet remain "hidden" for the user (i.e. stored in system private storage, not on the SD-Card).

You can use the system settings content provider to store the value like so:

final String myKey = "verySecretKey";
final String myValue = "verySecretValue";
final boolean isSuccess = System.putString(getContentResolver(), myKey, myValue);

And to retrieve it you can do:

myValue = System.getString(getContentResolver(), myKey);

And yes, on a rooted phone a handy user might get hold of the persisted value, but in that case nothing is holy anymore and @Adam's comment will get valid: You shouldn't store the data on the device.

dbm
  • 10,376
  • 6
  • 44
  • 56
  • Does this actually work? It seems like such a hack, and something Android wouldn't allow (or might break in a future release). Settings.System is meant for... well, system settings, not applications personal storage. – Tom Jul 07 '12 at 15:27
  • Yes, it works and I also expect it to work, especially as there is is a documented public API for it. Also, checking the documentation (http://developer.android.com/reference/android/provider/Settings.System.html), one may take note of that the `putString` method seems to be enabled for "general purpose key-value storage", while the other `put...` methods seems to be used for primarily modifying existing keys (but that may be a matter of interpretation). – dbm Aug 06 '12 at 10:07