If I hash client side the server will never know my password. If the server hashes the password, that is effectively the same as storing the password in cleartext.
/edit: Security wise sending the password, means you trust the server to handle the password correctly. For all we know it stores the plaintext password. If we send the hash, we KNOW that it does not store the password. It's an important distinction to make in real world systems. No matter how much best practices dictates to not reuse passwords, it happens as long as humans are involved.
(Note: edited to make it more clear that hashing only on the client is insecure.) I think it is true that hashing on the client in addition to on the server offers a little security boost since if someone is able to snoop a login, they will only see a hashed password, which they can use to compromise the user's account on the site being accessed but not on other sites where the user may use the same password (assuming you use a salted hash). Server hashing guards against the case where someone steals the database but not against the case where they snoop logins (and hashing only on the client wouldn't guard against this). Also, it might be practical to use more rounds of bcrypt on the client, but this is hard to say. Maybe you were downvoted, though, because you said server hashing is "effectively the same as storing the password in cleartext." Actually, the main win is probably from hashing on the server; the boost from also doing it on the client seems relatively minor.
If we send the plaintext password we don't know that the server handles it responsibly. We don't know if they had to push an update under time constraint means that they now store passwords in plaintext. What we know is that we send plaintext password to the server on every login, that should, in a threat model, be considered as not using hashing at all.
On the other hand, if the password is hashed client side, we KNOW that it cannot be stored as plaintext, because the server never knows it.
I've done this before in a site, probably badly. But the way I handled it is that on sign up I hashed the password on the client side and stored that once. Then during login as part of the form I also included a "challenge" (i suspect I was not rigorous with it) that went with it, so I had: HMAC(HASH(password), challenge), and that's what got sent across. Since the server had the original HASH(password) and the challenge it could verify that you knew the password without either the hash or password being sent. I know for a fact that I wasn't handling replay of the challenge properly but it wouldn't be too difficult to deal with it (add the time and have it expire after so long). But I definitely had other problems with it (no SSL, and probably bad sidechannel issues).
If we talk about "hash the password before sending to the server" this procedure is what we're talking about (or something similar). Surely people aren't thinking of literally just hashing the password and sending it on its merry way? If we say "symmetric encryption" we don't mean we're going to do AES(block_n, key) either (ECB mode should never be used for anything).
yea i think the bits i'd shoot for with this now are
1. Bcrypt(or scrypt, or similar) for initial hash of password. (used PBKDF2 i think before).
2. Add time expiration to the challenge-response
3. Rate limit the challenge/response per account
4. make sure to use a good hash for HMAC() (was using sha-1 since JS was much slower then).
Ideally I'd also have a single challenge/response token per user and not let you get several to try against (i.e. invalidate old ones) but I'm not sure how I'd make that scale well. Maybe a salt+counter put into a hash (like HOTP) and then after a token is used invalidate all tokens with the counter less than the most recently attempted version?
And yet the server sends you the code to hash your password. Either way, if the server compromised, all bets are off. That said, there are architectures where this may make a difference, but they certainly aren't the usual case.
The difference is that I can verify the code, and the data send. If I send the password to serverside hashing, I can only trust the server to handle it correctly. Security wise that is a fairly important difference.
Are you saying you not only know of some website that does password hashing client-side but that you also inspect the javascript that site serves you every time you login?
As a user, any password you supply should always be treated as a shared secret between you and the service. We are well past the age of using the same password for everything.
> If the server hashes the password, that is effectively the same as storing the password in cleartext.
The server hashes passwords to prevent a database leak or bad actor from effectively compromising all accounts at once. It is also a service to the users who — despite being advised not to do so — reuse the same password everywhere. With a proper hashing method (e.g., bcrypt, PBKDF2) these hashes are effectively one-way.
As a user, any password you supply should always be treated as a shared secret between you and the service. We are well past the age of using the same password for everything.
Agreed, but that does not change the fact that you shouldn't be sending the password to the server, since that is thrusting that the server handles it correctly. If you gurantee that passwords will never be reused, the password is as good a secret as the hash. But if you cannot gurantee this, and that includes nearly all real world systems with humans users, it makes an important difference security wise.
If you are not reusing passwords, you should (from a security standpoint) not care at all. Without client-side hashing the server gets a bunch of characters that are exclusively used for that service, and with hashing it gets another bunch of characters.
The only situation where client-side hashing could matter is if you are reusing passwords; but the user can trivially mitigate that by not reusing passwords in the first place.
From the standpoint of the operator providing the service, security is not increased by one iota by hashing on the client. In fact, it can decrease security. By following the NIST guidelines, most up-front password rules are relaxed. However, to guarantee password strength, NIST recommends to do a check against common password lists and dictionaries to guarantee a certain level of entropy. So even if you meet the minimum length check, a password like 'password1980' should fail (common password plus a year). This check cannot easily be done client-side, because from a security standpoint the client is untrusted (especially so with HTTP and HTML/CSS/JavaScript) and it would require a substantial amount of data to be sent to the client (password databases, word lists, etc.). Even without these additional checks, the server still needs to know if your password meets the minimum length requirement. It can only do this reliably by inspecting the password (again, assuming a web browser is the client).
So when you enter a new password, the server should check if the minimum length and optionally the minimum entropy are met. At that point the server already 'knows' your password, so client-side hashing whenever you login normally is redundant.
Replying to Freak_NL here since I cannot make the thread deeper.
If you are not reusing passwords, you should (from a security standpoint) not care at all.
From a user stand point I agree. But that is not what I'm tryin to argue.
From the standpoint of the operator providing the service, security is not increased by one iota by hashing on the client.
That is not true - it absolutely matters for service providers. If my service verifiably hash client side, and I only ever see the hash, I can gurantee that in the scenario where the database is breached only a hash is leaked. When my service cannot verify, enforce, or reasonably gurantee that users do not reuse passwords, it means that in the event of a breach less information is leaked.
> However, to guarantee password strength, NIST recommends to do a check against common password lists and dictionaries to guarantee a certain level of entropy. So even if yo meet the minimum length check, a password like 'password1980' should fail (common password plus a year). This check cannot easily be done client-side, because from a security standpoint the client is untrusted (especially so with HTTP and HTML/CSS/JavaScript) and it would require a substantial amount of data to be sent to the client (password databases, word lists, etc.). Even without these additional checks, the server still needs to know if your password meets the minimum length requirement. It can only do this reliably by inspecting the password (again, assuming a web browser is the client).
The password list to check against is at worst a few megabytes. Considering that we have JS libs that are larger, I fail to see this as a significant issue. Besides we already know how to encrypt such that I can send an encrypted password to you, where you can, without knowing the key, can verify simple claims about the data.
So when you enter a new password, the server should check if the minimum length and optionally the minimum entropy are met. At that point the server already 'knows' your password, so client-side hashing whenever you login normally is redundant.
If we accept your thesis that we must send the password to the server upon changing it, we could still use client side hashing for a marginally improved security model.
> The password list to check against is at worst a few megabytes.
People stuck on a slow mobile network would tend to disagree.
> Besides we already know how to encrypt such that I can send an encrypted password to you, where you can, without knowing the key, can verify simple claims about the data.
The server can't verify such claims without actually inspecting the password because the client is (from a security standpoint) untrusted. In the HTTP/HTML web client/server model, there is no effective way for the server to guarantee that the client is truthfully executing certain algorithms. That's fine, but it does mean that the server is the only source of truth for these type of security claims.
> If we accept your thesis that we must send the password to the server upon changing it, we could still use client side hashing for a marginally improved security model.
That's a dangerous road to take. Such a marginal security improvement still comes at a cost of increased complexity and maintenance burden. If users don't like the idea of sending passwords to a remote server, they should request that the service implements a two-factor authentication solution instead.
People stuck on a slow mobile network would tend to disagree.
That is picking my comment out of context. Fortunately we don't change passwords all that often. But that was not my point - rather that we already accept so much JS bloat on the web, that doing the same for password change is no different except it provides some actual benefit.
The server can't verify such claims without actually inspecting the password because the client is (from a security standpoint) untrusted. In the HTTP/HTML web client/server model, there is no effective way for the server to guarantee that the client is truthfully executing certain algorithms. That's fine, but it does mean that the server is the only source of truth for these type of security claims.
Not true. Zero-knowledge proofs can prove that "This hash comes from a password that meets all requirements", without providing the password to the server, yet it knows that it is good.
That's a dangerous road to take. Such a marginal security improvement still comes at a cost of increased complexity and maintenance burden.
Not at all. This is security best practice; lock things down as much as you can, and only open up for attack vectors when you have to.
/edit: Security wise sending the password, means you trust the server to handle the password correctly. For all we know it stores the plaintext password. If we send the hash, we KNOW that it does not store the password. It's an important distinction to make in real world systems. No matter how much best practices dictates to not reuse passwords, it happens as long as humans are involved.