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?
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.
Whoops. The protocol you described is actually secure against that, since your login passes the preimage to the server for hashing and then comparison.
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.
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.
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.
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.
"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.