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.
Related
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.
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.
I am told to analyse the behavior of a web application and noticed that it generates password reset tokens based on the username+password combination. That means that if username and password combination of the account stays the same during the resets, the generated reset token stays also the same.
So it is NOT random and not based on a time stamp or anything that changes frequently.
It does not look random to me at all. But what is it?
I checked several Java functions like UUID, that generate tokens, but their output does not look like the tokens I am looking at.
Has anyone an idea what (Java function) generates this kind of tokens?
Account B
token=YwQAAAAAAAAmONpWfOI-dGQoZBbXxUaApbRQ7E
token=YwQAAAAAAAADIDSPpW_5vC8AvpNTi5LIgQZ080
token=YwQAAAAAAAAg5NcxcGeRWXA2m_K0cm0TNx8rO8
token=YwQAAAAAAAA0H4tkoER8tDfMR_V_TT3BPfC43g
token=YwQAAAAAAAApFrrJCJvb_zH0p5f-HkIt7EtWgA
token=YwQAAAAAAAAiDeQFrxpTSwrFNCV4AQW0sdoiyw
Account A
token=TwQAAAAAAAAi6M6tduIa6EdB3-VB1J_l8Cyza8
token=TwQAAAAAAAAM-yFuFKebUZA-2q0YgwnJeGrZuo
token=TwQAAAAAAAAg0We7RWTMM9PYv68RCJMUG_MuBw
For me this looks like a Base64 enoded something. Try to decode your token with Base64 and look what it looks like.
I think they are doing something like this to generate a base65 compressed string
Sign a string using SHA1, then shrink it using url-safe base65
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.
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()