How to hide public key on android? - java

Android's security manual says that it is not safe to keep public key (used for Android market) just as a string and it should be hidden/encoded somehow.
Can somebody please provide me with example how it can be done?
(I don't have separate server, so it can not be stored there)
Upd. Believe, this is quite common task related not to Android, but to other apps also.

The relevant text from the page you linked to is this:
Important: To keep your public key safe from malicious users and
hackers, do not embed your public key as an entire literal string.
Instead, construct the string at runtime from pieces or use bit
manipulation (for example, XOR with some other string) to hide the
actual key. The key itself is not secret information, but you do not
want to make it easy for a hacker or malicious user to replace the
public key with another key.
That's pretty much all you need to know. There's no harm in people knowing your public key, the potential harm here is that someone replaces the public key in your program with their own in an effort to divert in-app purchases to their own account.
They're suggesting that you make it more difficult for that attacker by storing the key in separate pieces or XORing the key with some other string. Now, instead of just pasting their key over yours, they have to figure out what transforms you're doing to the string and make their own key fit that pattern. This is more work and might deter casual attackers, but won't prevent someone who is really determined.

If you use the Keytool utility this is all done for you. You'll get a .keystore file on your local computer containing your private key(s) that is encrypted with a password; keep that file and the password secret and you're secure.
http://developer.android.com/guide/publishing/app-signing.html
In fact I believe the Android plugin for Eclipse even does all of this for you automatically.

On the public key, you can hash it and save it as a hash value. Better yet would be to salt the hash value with something you would know when you need to get the hashed value back. May be something like user name, or ESN. Look at android.telephony.TelephonyManager.getDeviceId()

Related

Generating a secure cookie token to store persistently

I am trying to create a login and register page for my website. I am looking to use cookies in order to track a users session however I'm trying to implement it in the most proper and secure way. I've tried looking at tutorials and forums but most of them are outdated and use techniques that people comment are not secure. I understand tokens needs to be randomly generated and encrypted so I found one response that suggested to use a MessageDigest on UUID. But I found more articles suggesting that this may not be as secure as I think... Any suggestions on a secure way to generate cookie tokens to store in my db?
When I tried using the UUID method I got stuck on how to place it into my db since I'm having trouble finding how to turn it into a string. Here is my code...
UUID uuid = UUID.randomUUID();
MessageDigest salt = MessageDigest.getInstance("SHA-256");
salt.update(uuid.toString().getBytes("UTF-8"));
Your current method is, well, rather terrible. Consider if I, an attacker, learnt that my victims UUID is some value x. I could then simply take the SHA-256 hash of x and store this as a cookie on your website. Tada. I'm now impersonating my victim.
In saying that, a very secure way to produce tokens for login systems is something relatively similar. Consider the following JSON object:
{ "expiry": "1:30:00 24/10/2012", "userID": "F68D4A77DC34" }
If we stored this JSON object as a cookie on the client-side, it would be an excellent way to determine who our user is and when this object expires and the user needs to login again.
But wait, this won't work, because anyone could change the user ID or the expiry and your server won't know!
We can solve this easily by introducing an HMAC. An HMAC is a Hashed Message Authentication Code. We first generate (once, ever) a random HMAC key, k, to use on the server. This key should remain on the server and never be transmitted.
When a user logs in, we create a JSON object similar to the one above and then feed it through an HMAC (say, HMAC-SHA256) with k as the key, and then append the result of this to the JSON object as base64 encoded bytes. It sometimes helps to use a splitting character too, say ".".
We then end up with the following:
{ "expiry": "1:30:00 24/10/2012", "userID": "F68D4A77DC34" }.ScvlfpUDqgxtDPH4jsK44d+4cMNG+5yCvASJkVEI11o
This token would be fine to use exactly like that, but some people like to base64 encode the JSON too. We end up with something like this in that case:
eyAiZXhwaXJ5IjogIjE6MzA6MDAgMjQvMTAvMjAxMiIsICJ1c2VySUQiOiAiRjY4RDRBNzdEQzM0IiB9.ScvlfpUDqgxtDPH4jsK44d+4cMNG+5yCvASJkVEI11o
It is easy for us to verify that this token is legitimate by taking the JSON object, performing the same operation again, and then comparing the result of the HMAC with the one that is attached to the token. If they match, we know that our server generated the token and that it is legitimate.
There appears to be some misconceptions about what this "secure" token actually means.
It can be anything, in theory. You could use a username, or an incremental id counter, or salted hash of the username, or a uuid.
The question is what are you using it for and why?
If you're using it because you just want information on how long requests are taking, a number works just fine (in theory; not saying I recommend it, more on that later). You don't lose anything major if someone fakes the id number and why would they? They don't see an actual benefit from it.
If you're using this token because it determines who a user is for permissions purposes, then obviously your goal is to make it so it can't be faked. If you want it to be faked, then you should make it truly random and unique. So you could, quite easily, just use UUID.randomUUID().toString() - This is highly unlikely to be spoofable as someone would need to know the exact nano-second precision on your machine as well as the ability to know what the state of the random number generator for the other bits of the uuid are. And that simply won't happen.

Keep the value of a string secret

I have a String in my Android application (in Java) that is actually a key to encrypt and decrypt messages.
It's a simple String that I declare like this :
final static String myKey = "THEKEY";
The key never changes (and it will never be displayed in the app, nor sent through network or something else, it "stays" in the app).
Is there a way for people that have the APK to get the value of this string in my app?
If the answer is yes, what is the best way to be sure that the value of a String can stay secret?
Is there a way for people that have the APK to get the value of this string in my app ?
Yes, via decompiling.
what is the best way to be sure that the value of a String can stay secret ?
Remove it from the APK. Or, do not worry about it being discovered.
There are steps you can take to make it incrementally more difficult to retrieve the value, such as using DexGuard to package your production app. However, this will not deter somebody who really wants the value.

Secure way to use password in java file

I am developing an android application through which i am sending a mail via GMAIL API.
To send mail via GMAIL API i have to give them my ID and password.
GMailSender m = new GMailSender("myemailhere#gmail.com",
"mypasswordhere");
and i know writing password like this is not at all safe as my password could easily be stolen by extracting my apk and alsostoring the password in strings.xml is also not secure as xml can also retrieved.
my question is-
Is there any other way to write password in my file so that it remain secure??
The short answer is not. You shouldn't store your password anywhere in the code or in any file.
Even if you encrypt it like someone said you will have to store it's decryption algorithm/key somewhere in the code, which will be easily reverse engineered.
No,It's not safe to store passwords on the device.
small advice is always store passwords in char[] in encrypted form rather than storing in a String whenever it is mandatory to store.
Since Strings are immutable in Java if you store password as plain text it will be available in memory until Garbage collector clears it and since Strings are used in String pool for re-usability there is pretty high chance that it will be remain in memory for long duration, which pose a security threat. Since any one who has access to memory dump can find the password in clear text and that's another reason you should always use an encrypted password than plain text. Since Strings are immutable there is no way contents of Strings can be changed because any change will produce new String. So Storing password in character array clearly mitigates security risk of stealing password.
Storing passwords is not considered safe, and shouldn't be done if at all avoidable. There are a few considerations, if you have to for some reason.
The best place to store such things is in private SharedPreferences. These are not readable by anything but the app, or rooted devices. Do not store on external storage!!!
Encryption can always be undone, but if you have to, then it would be better than nothing, requiring more work to undo. Use a key which is unique to each device.
Some sort of a token, such as is used by Oauth, could be a solution. This isn't perfectly secure either, but it could be.
Google provides more secure APIs for it's functions. You really should look in to that.

Anti-hack solution for a secret key in Android app?

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.
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.
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.

exchange of public key as a serialized object

How to exchange the public key to the client place. i have encrypted a document(text file) using RSA algorithm by using private key and then stored the public key as an java.security.Key object in a file using serialization.I want to know about the integrity of the serialized public key object whether it is safe option to do or any other option available.
A public key is usually just exchanged as a piece of text. It is then imported into a keystore. The exact method of doing is depends on the implementation (I've always used PGP).
I wouldn't expose the key as a serialized form of java.security.Key because it's not really standard. The key in it's simple form is the standard form of interchange.
On exposing the key as a download: it's public, so there's nothing an intruder could do by downloading your key. The only thing that could go wrong is that someone could fake your server and host a different key. Then sign with that key's private key and claim to be you. Of course you could have the same issue if you mailed it to somebody. But then at least you would know who you mailed it to.
The safest approach is to spread the key out-of-bound. Like on a usb stick.
Depending on your cause, I think you can live with the risk.
Joeri has answered on the security aspects - I have nothing to add about that.
The main problem you might have is the serialized representation changing between library versions, which is a potential issue with any use of Java serialization.
Of course there are other ways to do it. The RSA public key should have an industry-standard encoding which you can access using the getEncoded() method. This gives you an array of bytes which you can write to a FileOutputStream. So it's really easy.

Categories