But you can do fancy cryptographic things where the server never sees the password and it's still secure. like the entire field of public key cryptography, diffie-hellman key exchange, etc.
Someone in another part of this thread mentioned the "Web Authentication API" for browsers, which I'm not familiar with, but is possibly trying to approach this?
It ties in with the credential management API (A way to have the browser store login credentials for a site, a much less heuristic based approach than autocomplete on forms) and basic principle is generate a key pair, pass back public key to be sent to server during registration. On login generate a challenge value for the client to sign. I don't think iirc the JS code ever sees the private key, only the browser sees it.
edit: considering someone eavesdrops on the connection, otherwise that's a whole different kind of vulnerability
register: send (username, user_salt, HMAC(user_salt, pwd))
login: send (username). retrieve user_salt. retrieve a server_salt generated randomly. send HMAC(server_salt, HMAC(user_salt, pwd))
But now your password is effectively just HMAC(user_salt, pwd), and the server has to store it in plaintext to be able to verify. Since plaintext passwords in the db are bad, this solution doesn't sound too attractive, unless you were suggesting something else.
--
Server stores hashed-password, hash-salt, and random-salt.
Server sends hash-salt, and random-salt to client.
Client uses user password and hash-salt to generate hashed-password.
Client hashes hashed-password using random-salt.
Client sends hashed-hashed-password to server.
Server grabs stored hashed-password and hashes used stored random-salt to check for match against client's hashed-hashed-password.
--
So the only thing this actually does is not share the text of the password that the user typed to the server. But at a technical level, now the hashed-password is the new "password".
Let's say the database is compromised. The attacker has the hashed-password. They make a login request to fetch the random-salt, hash their stolen hashed-password with it and send that to the server. Owned.
Along with being more complicated with no real gain, this also takes the hashing away from the server-side, which is a big negative, as the time that it takes to hash a password is a control method used to mitigate attacks.
Just send the plain-text password over HTTPS and hash it the moment it hits the server. There's no issue with this technique (as long as it's not logged!)
> Alternatively a timestamp would be just as good.
I don't see how that would work at all.
I also don't see the need to go any further in detail about how this scheme will not be better than the current best practices.
Never. Roll. Your. Own. Crypto. https://security.stackexchange.com/questions/18197/why-shoul...
Incidentally, I really resent how it's impossible to have a discussion of anything at all related to cryptography on HN without somebody bringing up the "never roll your own crypto" dogma.
If the ideas being proposed are bad, please point out why, don't just imply that everyone except you is too stupid to understand.
Edit:
I just reread your comment above and you did a perfectly good job of explaining why it's a bad idea, I must have misunderstood first time round: it's a bad idea because now the login credentials get compromised in a database leak instead of a MITM, which is both more common in practice and affects more users at once.
Sorry for saying you didn't explain why it is a bad idea.
So now _this_ is effectively just "the password", that needs to be protected, even though you're storing it server side.
If an attacker has it, they can go through the protocol and auth -- I think, right? So you prob shouldn't be storing it in the db.
All you're doing is shuffling around what "the password" that needs to be protected is, still just a variation of the original attempt in top comment in this thread.
The reason we store hashed passwords in the db instead of the password itself is of course because the hashed password itself is not enough to successfully complete the "auth protocol", without knowing the original password. So it means a database breach does not actually expose info that could be used to successfully complete an auth. (unless they can reverse the hash).
I _think_ in your "protocol" the "original" password actually becomes irelevant, the "salted hashed password with it's salt" is all you need, so now _this_ is the thing you've got to protect, but you're storing it in the db, so now we don't have the benefits of not storing the password in the db that we were hashing passwords in the first place for!
I guess your protocol protects against an eavesdropper better, but we generally just count on https/ssl for that, that's not what password hashing is for in the first place of course. Which is what the OP is about, that _plaintext_ rather than hashed passwords ended up stored and visible, when they never should have been either.
Cryto protocols are hard. We're unlikely to come up with a successful new one.
This is exactly the same: the seeded hash is the password.
Also, hashed passwords shouldn't be logged either.
No [0,1...n]. Note that these articles are about encryption, but the arguments against javascript encryption apply to hashing as well.
Also consider that no one logs this stuff accidentally to begin with. If the entity controlling the server and writing the code wants to log the passwords, they can rewrite their own javascript just as well as they can whatever is on the backend. There's nothing to be done about people undermining their own code.
[0]https://www.nccgroup.trust/us/about-us/newsroom-and-events/b...
It's possible. You create an object called Foo (possibly a serialized data like a protobuf, but any object), and you recursively dump the whole thing to the debug log. Then you realize, oh, when I access a Foo, sometimes I need this one field out of the User object (like their first name), so I'll just add a copy of User within Foo. You don't consider that the User object also contains the password as one of its members. Boom, you are now accidentally logging passwords.
Creating a User object that holds a password (much less a password in plaintext) seems next level stupid to begin with, but fair enough, I guess it could happen.
It can happen if requests are logged in middleware, and the endpoint developer doesn't know about it. It's still an extremely rookie mistake though, regardless of whether it was done accidentally or on purpose.
Maybe there could be a standard way to signal the beginning and end of a password string so logging software can redact that part.