Hacker News new | past | comments | ask | show | jobs | submit login

The hashing should be done in the client's browser. The plaintext password should never reach the server (which is capable of sending emails).



Actually, I think "wut" was a reasonable response.

If the browser hashes the password, that just makes the hash the plaintext password. You've accomplished nothing.


There's one big win here I can see: your passwords don't exist in a vacuum. Many users, whether you like it or not, are going to be using the same password for a number of other websites.

By sending the hash and never letting the plaintext password hit the air, the worst that can happen is breach of your login system, you will not be responsible for someone in a coffee shop with wireshark sniffing out people's passwords, which can be applied to multiple websites.


Or, you do the registration process over SSL.


Indeed, a scheme like hashing-in-the-browser to keep a plaintext password "off the air" is essentially a homebrewed effort to replicate a secure connection.

IE, doing this is a mistake because you may be smart but you probably haven't put your secure connection through everything that SSL has been put through.


Not necessarily, if I understand the situation correctly. In this notation, -> represents communication between components, and | represents the boundary between local and remote communication, which we assume is encrypted/decrypted appropriately.

On account creation,

  password -> hash -> | -> stored
Upon account creation, I provide my password, which is hashed locally. The hashed version of my password is passed over the network and stored on the other end.

Logging in,

  password -> | -> hash -> compare
Upon logging in, I provide my password and send it to the remote server. The remove server hashes my password and compares it to what it stored previously.

Hence, if someone intercepted my hash, it's the same situation as if they looked in /etc/passwd on a multi-user Unix system. That is, it's more information than nothing, but it's non-trivial to use that information to figure out my password.

Is there a flaw in my reasoning?


That's an interesting idea, but I don't know what you're protecting against. You're still providing the plaintext to the remote end eventually, so I assume you trust them. You're assuming the communication is encrypted.

What does this scheme protect you against, compared to the normal technique (part #2 in your example)?


If your password is never stored in plaintext, it's less likely to be leaked, either maliciously or inadvertently. It's the same rational for not storing plaintext passwords on a Unix system.

Like on a Unix login, I have to provide the actual password to the service. But measures can be taken to ensure not only is the password itself never stored, but even that the memory that contains the password is appropriately zeroed after use. It's not a matter of the user trusting the service, it's a matter of the service being cautious with itself.


There's no need for a new protocol; lots of websites manage to never store passwords today. I guess your protocol does provide some assurance that the other end isn't going to store anything but the hash. Unfortunately, anyone competent enough to implement it is already probably doing the right thing, and the people doing the wrong thing frequently have business reasons for doing it wrong.


That only protects you at account creation time. How about this:

Password hash function is h. Client creates password p, hashes it 1000 times.

Account creation: Client sends h^1000(p) to server in the clear. Server stores h^1000(p) in plain text. Attacker eavesdrops h^1000(p), which is useless.

Log in: Client either looks up h^999(p), or calculates it from scratch starting at p. Client sends h^999(p) to server in the clear. Server hashes this to get h^1000(p), which matches what it has stored. Server replaces stored value of h^1000(p) with h^999(p). Client is permitted to log in. Attacker eavesdrops h^999(p), which is now also useless.

Log in 2: Client either looks up h^998(p), or calculates it from scratch starting at p. Client sends h^998(p) to the server in the clear. Server hashes this to get h^999(p), which matches what it has stored. Server replaces stored value of h^999(p) with h^998(p). Client is permitted to log in. Attacker eavesdrops h^998(p), which, again, has become useless.

...

Once the client gets down to around h^100(p), server (which has also been keeping count) starts prompting client to create a new password before the hashes run out.

(If you run out of hashes, you're screwed. You can log in one last time by sending p in the clear and having it stored in plain text. Attacker eavesdrops p, which is useless here but may be extremely useful elsewhere for obvious reasons. After this, you can never log in again.)

NOTE: obviously this assumes the hash function is irreversible, mostly free from collisions and quick to execute. Also, the user should ideally NOT log in like 1000 times in a week. Both achievable goals, though.


The purpose of this is not to protect against eavesdropping - note I said that the communication with the server was encrypted and decrypted as appropriate. Really, I was just presenting an existence counter-example to the claim that if the browser performs the hash, the hash itself becomes the plaintext password. This is a scheme where the browser performs the initial hash, and the user still uses the same password.

That aside, the only thing it gets for you are less code-paths you have to worry about that handle the password in plaintext. It's an application of the principle to only communicate what is strictly necessary to function.


The only problem I see with this is in cases where you sign in from multiple devices. How would each device know which x (for h^x(p)) you are on? Is that something the server sends to each device at login time? Would that be a security risk? I don't know a lot about this so these may be stupid questions.


I believe you have just reinvented OTP, one time passwords.


Geez, you're right. I went all the way through the Wikipedia article on cryptographic hash functions looking for something similar to what I'd just described, but there was no link to THIS:

http://en.wikipedia.org/wiki/Hash_chain

The resemblence is actually spooky. I swear I've never read that article before now.


"Hence, if someone intercepted my hash, it's the same situation as if they looked in /etc/passwd on a multi-user Unix system."

Except that now the hash is your password, as far as the system is concerned. If someone intercepted your hash they could just pass the hash off to the site and they have full access. This isn't quite as bad as accessing the plain-text password (which potentially is shared across multiple sites) but it's still bad.

Also, there's an easy workaround for this problem, using SSL for login.


This increases the password space (assuming a cryptographically strong hash), but if the datastore is compromised, an attacker can just bypass the client hashing (by changing JavaScript, etc) and just pass in the hash itself.


Yes, if someone breaks into the server, and changes the code for the login process, they can get around this. But that's always true. The server is a higher priority target than a single account. If your scenario requires breaking a higher priority target than the one in question, it's not really a security hole.

Similarly, someone can compromise my account on a Linux box if they get root access. They won't know my password, but they can change my password or just replace the login program with their own. But we consider getting root access a higher target that compromising a single account.

In other words, this is begging the question.

edit: I must have responded to a different understanding.


Whoops. The protocol you described is actually secure against that, since your login passes the preimage to the server for hashing and then comparison.


I think this actually does protect you from exposing your password to an attacker, but only at account creation time. If the attacker waits around for you to log in conventionally at some later time, then it's over.


Go read http://en.wikipedia.org/wiki/Digest_access_authentication and become informed on how you can do hashing on the client's browser and actually gain something in the way of security.


Digest mode has the issue that you need the plaintext password on the server side in order to do the authentication.


You clearly didn't read the link I directed you at. If you had you'd have seen that you only need MD5(username:realm:password), and would have been pointed at JBoss's DIGESTAuth implementation as an example of an implementation that does this.


"You clearly didn't read the link I directed you at." I do believe your tone is rather counterproductive to the purpose of this forum.

I did in fact read the article, and I do now agree that you only need to send MD5(username:realm:password) to the remote server to do the authentication.

The problem that I do see is that it is trivial for a MITM to either intercept the transaction and force the client into a less secure mode (ie. basic auth), and then read in the password, or else just reuse the auth credentials for another transaction.

I would recommend that you look at http://en.wikipedia.org/wiki/Secure_Remote_Password_protocol and the concept of a "zero knowledge password proof" which seems to be the concept you were looking for.


Riddle me this batman: how does one get MD5(username:realm:password) onto the server?


The normal way is to capture that information in a sign-up page that is served over https. The point of digest authentication is not to replace https for what it is necessary for. It is to allow http and authentication to be used more securely than plain text authentication can be.

Incidentally your snideness is not appreciated. Generally something doesn't get to be a widely implemented RFC without the obvious questions having been asked and answered.


Capturing that information in a sign-up page that is served over https sounds an awful lot like the plaintext password is going to reach the server at which point the server will be mathematically capable of displaying it. That happens to defeat the entire purpose of this little subthread.


Your understanding of this subthread is very different from mine. I'm talking about practical security options for practical websites. In that case you don't care about information that was transiently present in the server for a fraction of a second once, you care about information that has been persistently stored.

But if you want such a ridiculous requirement, you can have JavaScript on the signup form that computes the hash on the client and sends it to the server. That form still needs to go over a secure channel (eg https) because the information sent, while not including the plain text password, is sufficient information for a sufficiently motivated attacker to get access.


We may actually be in agreement. I don't want such a requirement, it came from here http://news.ycombinator.com/item?id=2414550 and the link I first replied to, http://news.ycombinator.com/item?id=2414859

Your reply, coming where it did in the thread, gave the impression you thought digest auth somehow avoided ever sending a plaintext password to the server.


I was skimming the whole discussion and had missed that context. In that case I think we are in agreement.


Yes, but if we have hash(plaintext + site_specific_salt), then even if I use the same password for different sites and the hash from one of them is intercepted, it still takes a while until the others will also be compromised. I didn't say the system was perfect, but still better than sending the password in plain text.


I believe a similar idea (use hmac(url, password) as a password for websites) is used to great effect by a firefox plugin.

Also, please do not use hash(x + y), use hmacs. String concatenation in hashing breaks some of the complexity guarantees and will lead to your hashes getting cracked faster then you'd expect.


Yep, Etsy used to do that back in their more incompetent days. The only site I've seen that had a 'md5.js' script, seemed kind of unusual...


wut.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: