5 ms·
The point of hashing is from the difficulty of reversing it; generating a string that when hashed matches that value should be difficult. That way, even if some
by lt 15y ago
The point of hashing is from the difficulty of reversing it; generating a string that when hashed matches that value should be difficult. That way, even if someone has access to the hashes, he is unable to login - he needs the password.
If you accept the hash from the client, anyone having the hash is able to login, making hashing pointless.
- mikeash 15y agoIt's not hard to fix that. You have the server send the client a random salt each time. The client then sends back a hash computed with that salt, and the server doesn't accept the same salt more than once. Done right, the server never sees your plaintext password and replay attacks still fail.
- lt 15y agoI don't see how that can work. What would the server compare the received salted hash with, if it has never seen the plaintext?
- mikeash 15y agoYou do a double hash. Basically, toSend = hash(salt + hash(password)). The server stores hash(password), not password.
- kbolino 15y agoThe difference between hmac(salt,hash(password)) and hash(password) is trivial when the salt is known. It doesn't matter that the server only accepts the salt once, if the server is willing to produce another salt for the next attempt. If the server limits the number of salts it will produce in a given timeframe, it might as well limit the number of attempts to begin with, and so there's no point in "double hashing."
- mikeash 15y agoThe goal, I believe, is to prevent recovery of the plaintext password so that it can't be used to gain access to other accounts with the same password. The double hash prevents an attacker from ever obtaining that plaintext password.
- kbolino 15y agoThe issue was, I believe, in preventing a remote attacker who knows the hash from using it to authenticate[1]. That is why passwords are transmitted in plaintext then hashed and validated on the server side. You should never trust the client to perform your cryptography for you, because you have no idea who--or what--the client is. No amount of obfuscation can alleviate that fact. 1 http://news.ycombinator.com/item?id=3419700 http://news.ycombinator.com/item?id=3419700
- mikeash 15y agoYour comment about not trusting the client confuses me. You don't have to "trust" the client to do cryptography for you. You simply define the cryptography it has to do, and if it doesn't do it, then it doesn't produce what you need to log in. This is not an unusual practice, either. For example, any time you log into a remote computer using an ssh key, your ssh client is performing cryptography to authenticate you with the server. There is no problem in doing this, because the only way to perform the cryptography such that the authentication is successful is to have the right secret key. You could certainly write a custom ssh client that does some different cryptography, but that would be pointless, as the result would be an inability to connect. There are, I think, two goals at play here. One is what you linked: preventing replay attacks. That is fairly easily solved by doing a double hash with a randomly generated salt. There is no problem in "trusting" the client to do this, because if they don't do it the way you specify, they don't produce the correct result. The only (feasible) way to generate a result that lets you log in is by combining the random salt with the correct password. This is important because otherwise an attacker could sniff your traffic and then impersonate you. The second goal is in not having your password exposed if the site's database is compromised. Related, it would also be nice to not have your password exposed if the site is compromised and the attacker is watching incoming connections. SSL solves the first goal, of preventing replay attacks. Not having your password exposed if the database is compromised is solved by hashing passwords. However, if you send the password in plaintext (or encrypted in such a way that the other end can retrieve plaintext, as with SSL) then the last, related goal fails: an attacker with total control can grab your password if you log in during the time he has control. By doing hashing on the client, you can prevent that, and when implemented properly it can still avoid the rest.
- deleted 15y ago[deleted]
- Xylakant 15y agowhat you're describing is basically cram-md5. Which is nice if you're using plain http and don't want the password to travel over the wire. But both sides need the plaintext password. Otherwise the hash of the password replaces the password and is just as good as an authentication token as the password itself, i.e I just need the hash to authenticate, not the pw itself.
- ams6110 15y agoThe server needs the plaintext password once, to generate a salted hash. From then on, it can send the salt and a challenge to the client. The client hashes the password, salt and then hashes that with the challenge and sends it back to the server. The server hashes the challenge with its salted hash and they should match. This still has to be done over SSL because otherwise the JS doing this on the client side is subject to MITM.
- Xylakant 15y agowell. but if you're using ssl then you could as well send the password over the wire and have it properly stored with bcrypt on the serverside. And if I control the application I can make the client emit a plaintext password by sending an empty salt. The result is a simple hash of the password which can be reverted with a regular rainbow table. If the client uses bcrypt, I send a work factor of 1 and construct a proper rainbow table (that's rather simple). Or I could just have the javascript send the password in plain. So there's no gain here.
- mikeash 15y agoBut at least you can't recover the password to log into other sites. I thought that the main goal here was to avoid the scenario where an attacker recovers your password on one site and can therefore log in as you all over the place if you made the mistake of reusing it (as most people do).