Generating a secure cookie token to store persistently - java

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.

Related

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.

Java generated Token not random - but what is it?

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

Is there a way to verify if datas aren't altered during sending to a webservice (Using HTTP connection)?

I'm working on an Android project which send datas to my Webservice and store them in my Database. I'm using a HTTP protocol to connect to my webservice. Using JSON for data format.
I send to the webservice the datas and the HASH (SHA256) of these datas.
Before storing the datas to the database, I verify by using HASH
if what I've sent (datas) equals to what The Webservice received. If not, I send
an error message.
Sometimes the values of the HASH are differents which cause an error message, and no datas storing in the database
So my question : Is there a another method to verify if the datas
aren't altered during the sending operation?
The hash seems to work for your scenario, since you detect data modifications pretty well.
But a hash can be altered along with the data, so this is not a security measure against malicious attackers. If you're concerned about security, you might be interested in WS-Security.
Essentially, you must either use an encrypted channel (HTTPS) or sign your message.
If you don't trust the channel - you should use HTTPS. That's all. Trying to build your own integrity verification mechanism is trying to design your own security protocol and that is the last thing you want to do.
In any case, an unkeyed hash (like SHA256) that you're using is insufficient. An adversary who is capable of modifying the message is also capable of recomputing the hash of the modified text and sending it along with the message. You'll need a stronger primitive: the MAC (Message Authentication Code) http://en.wikipedia.org/wiki/Message_authentication_code
HTTPS give you this and more.
Hashing techniques would be the best choice here.
You can use any hashing algorithm like HmacSHA1 or MD5,etc.
When you are passing your data to server using Post or Get, first, create a token from the data by using any hashing algorithm. (please see below function that converts data into HMAC SHA1)
When you pass this data, pass the token as well to server. Now server will also use the same hashing algorithm that client has used, and server will create the token from the data that is passed with the request.
After that server will match the token generated with the token passed with request.
If both the tokens matches, the data that is passed with request is not tampered otherwise the data is tampered.
You can use following method to create token for your data:
/**
* Encrypts the data passed to it using Hmac-SHA1.
*
* #param dataToEncrypt
* data that is to be encrypted.
* #return The token that is generated after encrypting data.
*/
public static String convertDataToHmacSHA1(final String dataToEncrypt) {
String returnString;
try {
// Get an hmac_sha1 key from the raw key bytes
final byte[] keyBytes = HMAC_SHA1_KEY.getBytes();
final SecretKeySpec signingKey = new SecretKeySpec(keyBytes,
"HmacSHA1");
// Get an hmac_sha1 Mac instance and initialize with the signing key
final Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
// Compute the hmac on input data bytes
final byte[] rawHmac = mac.doFinal(dataToEncrypt.getBytes());
final StringBuffer stringBuffer = new StringBuffer();
for (byte b : rawHmac) {
stringBuffer.append(String.format("%02x", b));
}
returnString = stringBuffer.toString();
Log.e("Token", returnString);
return returnString;
} catch (Exception e) {
Log.e(TAG, "" + e);
}
return returnString;
}
currently you use a hash to verify the integrity of the data - assumming you use the exact same hashing on both ends this means youre getting corrupted data.
instead of just detecting data coruuption you could encode the data in an error correcting code so that you could reconstruct the original data at the receiving end even if it was corrupted on the way there
you can find such a library in the answer to this question - Java: ECC (error correcting code) library?
I think your method is a good one.
you have an heavy solution in 3 steps :
step 1 : send the data to android
step 2 : android receive the data and inform the web server what he get
step 3 : the server check every field and inform android if the orverall is correct or not.
but i think this solution is too heavy for most the case, it was to answer your question if there is another solution or not.
Do you need to read back the data, If not just hash it once and compare the hashes.
Dependant on the frequency of the hash being wrong could you give the application five attempts to getting it right before the error message.
Have you tried other algorithms like md5, ripe or crc? Maybe they are more efficient.
In my experience for small string i use crc but for login details i go with sha256 or sha512
and i just hash the password and compare the hashes. Then you dont have passwords sitting in your database.
Hope this helps!
Correct me if I'm wrong, but you are hashing in an attempt to detect one of two things.
Detect a "Man in the Middle Attack." (MITM) See here for more information.
Detect an unreliable network.
#Samuel Edwin Ward and #radai were talking about these two above.
Both concerns have reasonably good existing solutions that DO NOT involve you explicitly hashing your data.
Firstly, for reducing the likelihood of an MITM attack, use HTTPS. The client can establish the identity of the server with some confidence, and it also does quite a good job of preventing eavesdropping.
Secondly, to address your concerns about an unreliable network, use TCP...
TCP provides reliable, ordered delivery of a stream of octets from a program on one computer to another program on another computer. Wikipedia
I'm guessing you haven't done anything special (like use a UDP network or something), and your web service already uses TCP.
The issues you are seeing with your hashing comparison is likely to be due to an incorrect assumption in your application logic. I would suggest that you are comparing hashes of the wrong things.
As one of many examples that come to mind, some web servers will add things to the HTTP request as it is processed. This is how proxies work, for instance. This will give you different results when comparing a hash of the HTTP request as sent by the device, and a hash of the HTTP request as eventually received by the web server.
I suggest you read the inline links I have provided to assure yourself that your concerns about corrupted data have largely been addressed by existing solutions. If they aren't, at least you'll have a better understanding of why you feel you need to hash your data. :)

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.

How to hide public key on android?

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()

Categories