Jump to content
  • Advertisement
Sign in to follow this  
SymLinked

Login authentication. Encryption vs Hashing

This topic is 4155 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello everyone! I've been playing around with our login system (for our hobby project) again now. I coded it a while back. We used RSA to pass the AES key, but it was a pain to get working (probably because of my inexperience). A ton of problems I'm not going to describe here. Anyway, because of these issues and the fact that SSL does all that and is tested, I'm considering making the registration by HTTP/SSL and using hashes to pass the password upon login ingame. But I'm getting doubts, as usual. -_- Are hashes (say, 512 bit) really "secure"? I was thinking of hashing the password with some random number and sending it off to the server. I've read Hplus (I think it was his!) excellent article on this, but I felt some of this was missing and I had more questions than answers afterwards. I do realize dictionaries of all possible combinations from a hash can be made, but it would take very long. Wouldn't it? What does online games use, are there any whitepapers or articles on this? Sorry for the rambling and thanks for any suggestions you can give me.

Share this post


Link to post
Share on other sites
Advertisement
A hash is designed to be difficult to reverse. If the library writers did a right job implementing a known hash function (such as MD5 or SHA), then it will be difficult to obtain the original value from a given hash.

Where a problem appears is when you distribute several hashes, each corresponding to a salted value. This can give you information about the hashed value, especially if the salt is transmitted over a network. This weakens the hash function considerably, and makes you vulnerable to "smart", non-brute-force attacks that listen to a few logins and deduce the password from there.

On the other hand, you seem to be using a secure and encrypted connection (SSL) between server and client, so you could simply send the password along that channel without further scrambling...

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
A hash is designed to be difficult to reverse. If the library writers did a right job implementing a known hash function (such as MD5 or SHA), then it will be difficult to obtain the original value from a given hash.

Where a problem appears is when you distribute several hashes, each corresponding to a salted value. This can give you information about the hashed value, especially if the salt is transmitted over a network. This weakens the hash function considerably, and makes you vulnerable to "smart", non-brute-force attacks that listen to a few logins and deduce the password from there.

On the other hand, you seem to be using a secure and encrypted connection (SSL) between server and client, so you could simply send the password along that channel without further scrambling...


It might also be a good idea to hash all passwords in your database.

a large number of users will use the same password for multiple services, IF your db gets hacked you don't want the hacker to obtain all your users passwords as plain text. (If they are hashed it will atleast take a bit of time and you might be able to get a warning out to most of your users in time so that they can change their passwords on other sites (email, bank, webhosts, online games, etc.)

Share this post


Link to post
Share on other sites
Thanks Simon and ToohrVyk.

Quote:
Original post by ToohrVyk
Where a problem appears is when you distribute several hashes, each corresponding to a salted value. This can give you information about the hashed value, especially if the salt is transmitted over a network.


Even if the salt is unique for each connection, trough a PRNG?

Quote:
Original post by ToohrVyk
On the other hand, you seem to be using a secure and encrypted connection (SSL) between server and client, so you could simply send the password along that channel without further scrambling...


I don't have SSL between server and client, hence why I would like to move the registration over to SSL-HTTP via a web browser.

Share this post


Link to post
Share on other sites
First, there is no way to go from a shrunken hash (a fixed bit computation) back to a definate original value ... because the whole idea is you are collapsing multiple original values to the same hash.

For instance if you had just a 16 bit hash there are only 64k values, but there are more than 64k options for say a 20 byte string.

That doesn't mean all hashes are at all secure though. It is very hard to create hash or encryption algorithms that do not have various behaviors that are mathematically predictable. Hence one reason why people use industry standard algorithms instead of hand written ones (the industry standards have the negative consequences of having enormous efforts worldwide going on at all times to improve the hacking of them ... including many tools available to aid in that - but hand written ones are almost always extremely weak mathematically - so they only work until it becomes worthwhile for some entity with the will and the resources to hack it).

Another thing is, a 512 bit hash doesn't work well if the average password length is 4 characters ... you cannot really create differences from none ... you cannot add entropy into a hashing system because it has to be predictable from 1 run to the next.

I highly recommend AGAINST using any encryption algorithm on passwords UNLESS your client REQUIRES the ability to get back a forgotten password. No body, program or human should be able to read any password value you've secured and somehow get back to the original typed password. If they can do this you are opening your customers up to significant risk. A password is only as secure as the weakest site you've used it.

So the normal idea is to hash (not encrypt) tokenized things like passwords as soon in the chain as possible (things which you don't need a value from, just a comparison) - and store and compare only the hashed version.

Of course this requires that all things which must do the comparison have access to the hash algorithm and salt ... but this can be improved a little bit in multi-tier server type scenarios by letting a separate machine provide the authentication service. In distributed client oriented scenarios you just let the hash system be exposed, since it doesn't really provide any reverse characteristics the risk is not terribly high.

Share this post


Link to post
Share on other sites
Quote:
Original post by SymLinked
Even if the salt is unique for each connection, trough a PRNG?


Especially if the salt is unique for each connection. Look at it this way: if you are given a single hash and are told "reverse this", you'll be in trouble. However, if you are given 10 hashes and told "these are hashes of the same pass plus different salts", then you'll have more information from the 10 hashes than from a single one about the original hash.

Besides, if both client and server know what the salt is, then it's quite possible that anyone with read-access to the connection between them also knows what the salt is, unless the PRNG seed was transmitted through an encrypted channel in the first place, and the PRNG is crypto-level (Mersenne Twister, LCG and all the usual others are out).

Quote:
I don't have SSL between server and client, hence why I would like to move the registration over to SSL-HTTP via a web browser.


Well, that sounds like a good idea. Do it [smile]

Share this post


Link to post
Share on other sites
Most hashes are irreversible into input data. That doesn't mean they are secure.

Hash collision occurs when you have two inputs that result in same hash. If you allow 16-characters long ASCII passwords, but uses 32-bit hash, the number of collisions will be extremly high (there's only 2^32 different hash values).

That said:
- Hash or plaintext are equal in strength when transmitted over wire. Obtaining either will give attacker full access.

- Sending plaintext is worse, since it can be used elsewhere. Consider account management. If attacker obtains plaintext password, they can use it to access other services, possibly cancel your account. If they obtain hash, they cannot, since different services can use different hashing.

- Identity spoofing. It's possible to spoof the client into connecting to a fake server. If they submit plaintext (regardless of channel), they will expose themselves completely. If they submit salted hash, attacker gained almost nothing. This type of attack was made famous with eBay and amazon credit card info thefts.

- Plaintext is bad for another reason. For secure applications, plaintext MUST be erased the very second it's no longer used. Password string MUST be overwritten with zeroes once it goes out of the very most immediate scope. In addition, it should never be stored in any non-stack memory. Anything beyond that, and buffer overrun attacks will allow you to reveal the password remotely.

This last option may seem far-fetched. It's not.

Long story short. Security is probably one of the few problems in computer science where 80/20 rule doesn't apply. Security is only as strong as the weakest link (not 20% of security handles 80% of all situations).


Perfectly secure system (excluding possible OS flaws) would be something like this:

- Write custom control that doesn't store the plaintext value.
-- When user presses a character, that control submits to hash delta calculation
-- When complete, hash value is submitted, and memory location erased (zeroed out)

(technically this violates the stack only system, but unfortunately, unless OS supports some mechanism, there's not much else)

On server:
- When you receive the hash value, send it to remote server for authentication, zero out the network and any other buffers through which this value was received
- Authentication server sends back a true or false after a half second delay.

Whether you then choose to additionally encrypt the channel is irrelevant. Anything will improve the security.

Even with this, there's an incredible number of attack vectors, this merely prevents the obvious flaws in code.

So, long story short - don't store plaintext anywhere. If you have to, put it behind several processes. Send elaborate authentication hashes, adjusted with salts, so that obtaining the has alone isn't enough.

But above all - never ever under any circumstances over any connection send plaintext. Ever.

Hashes and other mechanisms are incredibly secure (relatively). This is why the most dangerous attacks don't attack hashes, but exploit external systems. The most extreme example of this is social engineering. It's also the most effective. Why spend years cracking the hash, when a phone call will get you the real thing.

Share this post


Link to post
Share on other sites
Quote:
Original post by Antheus
- Sending plaintext is worse, since it can be used elsewhere. Consider account management. If attacker obtains plaintext password, they can use it to access other services, possibly cancel your account. If they obtain hash, they cannot, since different services can use different hashing.


If you hash the password with some random crap, then it will only be valid for that login and not the next, so I'm confused. :) Perhaps you're talking about something else? Thanks for the link!

Based on what the others said, I guess simply hashing a password and sending it over is not considered secure enough for a login.

Share this post


Link to post
Share on other sites
If you dont allow numbers in your passwords and on every login, you put random numbers to random places of your password, that gives you the ultimate hash :) (or the same with special characters like ;><}{$ߤ÷׸¨˝§'"+!%/=)

Share this post


Link to post
Share on other sites
There's a couple things on this that is confusing to me. I've been thinking about doing this stuff for my logins, so now I'm really curious.

First, if you say do an md5 hash of a password from the client, and send it to the server, a sniffing intruder could sniff the hash, and just submit the hash to obtain access to the account. Hashing at least, secures the plaintext password so they do not know what that is. But in this case, it basically can be used as the password itself to login on their account (in game).

Now, I suppose you could have a seed negotiated from server to client to further complicate the hash, but couldn't that seed be sniffed as it made its way from server to client, and then the intruder would also know the seed key?

What piece of the pie am I missing, here? Even if you used that key to somehow further complicate the hashing, if that intruder has the client as well, and could reverse engineer it to learn the hashing methods you're using on the client side.

I guess I'm confused by the idea that in order for the client to know how to send the login, the server has to give it some kind of instruction. And if not, the client is hardcoded to know what to do, and thus, can be reversed engineered and cracked anyhow. So how do you securely synch these? At this point, all it looks like one can do is make it really difficult for an intruder, but not completely secure it, short of using some kind of encrypted channel like an SSL (which isn't promised, but highly secure).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!