I appreciate they where trying to protect passwords & promote security, but it definitely caught me off guard that this wasn't widely understood.
I think you meant "don't get"
Hashing in the client leads to a fair share of security issues, especially if it's not also hashed on the backend using the usual salted hashes.
There are protocols like SRP to do it securely, but it's non-trivial. And remember that such protocol is only useful if you trust the client implementation—it's kind of pointless for a third-party webpage or app.
Use randomized per-site password. Solves everything.
I've yet to see someone give a good reason to not hash on the client and the server... I would be curious to hear if you have any.
It's definitely non-standard though.
It might protect the password if the user is reusing it elsewhere, but it doesn't protect the account the password is securing during the intercepted transmission.
The MITM attacker can just replay the hash.
I can't see a reason why this hurts, but it's probably not worth it. The only benefit I can see it having is if the user reuses their passwords on other sites, as now a potential malicious MITM would have to brute force the client side hashed password in order to reuse it on other sites. They would still be able to use that client side hashed PW to authenticate to the service in question, though.
Basically, hashing on the client does absolutely nothing for the security of the transfer or storage of the password. Whatever the client passes to the server, whether it's hashed or not, is effectively their password, and intercepting that (again, whether hashed or not) would give an attacker the actual credentials of the user.
There is zero downside to doing an extra hash, except the chance that someone codes such a basic thing wrong.
But only if neither site uses salt, so salt all your hashes. (Not even a salt is necessary here, just a site-wide addition would be fine. Or honestly you could just use a hash that wouldn't be used by a site too dumb to salt their database.)
If you want secure password transfer, do not construct a ghetto solution with stacked hashes, but use a proper protocol like SRP (which, again, is pointless unless the client is trusted).
Especially in the case of Twitter, doing this provides absolutely nothing in respect to credential confidentiality as both sites of the transaction is written by Twitter.
"Assuming an attacker has broken TLS" - this makes no sense. If I had broken TLS, I could send you a login form with no hashing. I could modify your legitimate API requests, without the need for your credentials. I could take your token and forge requests as I wanted. All your assumptions go down the drain, as the security relied on the presence of TLS.
Basically, making this setup is generally harmful, while only providing negligible benefit in a doomsday scenario where all bets are off regardless.
If you truly want to have better security, you need an entirely different system. E.g., local private keys used to sign requests, or a proper password exchange/validation protocol. Smacking another hash on top does nothing good, and the idea is a good example of why normal people shouldn't crypto.
I agree with you on the general pointlessness of client hashing, though, and oh what a world if we had pub-priv keys for authentication instead of passwords...
The main issue is that security analysis is non-trivial due to the interaction of their security guarantees. The end-result is effectively a new hashing algorithm. Figuring out the properties of this new algorithm requires a new cryptoanalysis (which is more than just avalanche tests).
> It also flies in the face of common in-practice schemes (pre-bcrypt) like doing n rounds of sha256. There should be no real problem with doing the first round on the client.
Old practices are deprecated for good reason, primarily due to flaws. Looking at what we used to do it not that useful.
The main problem is that it's not just "n rounds". The hash on the client must be salted, and it must be salted uniquely for that credential set, and must use a different salt from the backend hash. Plenty of ways to mess this up, and that's before we're even consider the implementation details of salting.
Then comes the interactions between likely different hashes. All in all, it's pretty complicated.
> I agree with you on the general pointlessness of client hashing, though, and oh what a world if we had pub-priv keys for authentication instead of passwords...
Especially with the only sensible procedure being password managers, it's silly we don't have asymmetric authentication. :(
If it's true, the attacker just has to do additional hashings to crack the password.
Passive sniffing requires the same attack vector, and the idea of an attacker only utilizing passive attacks makes no sense.
The point is that additional hashing designed for the premise of "broken TLS" fails the thread model test: It is pointless, as the only time it is applicable is when everything is fallen apart.
Are thinking of encoding / decoding? If so it isn't used for passwords.
this obviously does not eliminate the need for other security measures, so it's possibly more a question of "is it worth it?"
If you're trying to argue that the user puts in, say, 60 bits of entropy, and that the hashing algorithm is going to accidentally throw out 10 of those to result in 50 bits of entropy, I believe that any hashing algorithm that did that in a way that anyone can exploit with realistic computing power (a computer smaller than the size of the solar system) would be considered irredeemably broken.
And then: By the password not leaving the system you avoid another issue with humans: If the hash is lost (accidental logging and locks leaking and such things happen) this won't allow to sign in to other accounts, where the lazy human used the same password.
For machine-to-machine communication tokens with higher entropy can and should be used.
2. It provides no additional security in the authentication process.
3. It provides no additional security-at-rest for post-breach protection.
Doing something like that ends up in the dangerous bucket of duct-tape crypto. I don't mind people playing with crypto, but things are not as simple as they seem, and "more" is not necessarily better.
Sure, if you're foolish enough to not hash on the server side then you're setting yourself up for failure. But I fail to see what the problem with hashing on the client side is?
Use SRP or similar if you need private password transfers (which again is still pointless if the client isn't trusted).
You shouldn't be sending passwords in any form over unencrypted HTTP, and there isnt a clear case for hashing or obscuring the password over HTTPS.
Hashing the password on the client limits the password entropy to entropy of hash you generate. Any addition entropy in the original password is thrown away.
Also naive hashing in the client just turns the hash into your password, all of the standard issues of transmitting passwords still exists (such as replay attacks as you mention).
This has nothing to do with client vs server. SHA1 of STRING will always have the same entropy wherever it is computed; it must, for the hashing to work.
EDIT: I suspect you are confusing PRNGs or KDFs with hashing. Entropy is relevant with the former, not the latter.
I'm not clear why you think this would be so. Hashes (with salts) prevent attackers from being able to derive the password, and can also be used in conjunction with nonces to prevent replay attacks.
You need both parties to know the nonce and the salt for this to work, so you’ll need to send it over. At this point what value are you gaining over just sending the password?
I get the impression you don't understand what the nonce and salt are, so I'll break it down.
The salt is used to make the hashes for particular values unique to this site. It generally does not change across the site, but it makes it impractical to use pre-computed hash tables to find the original values for a given hash. By using a salt, the site ensures that transmitted hashes cannot be trivially reversed.
The nonce is used to allow the use of an HMAC to create a one-time hash that cannot be reused. This would typically be implemented as follows:
1. Service sends NONCE, SALT
2. Client Sends password as SHA256(SHA256(ClientPasswd + SALT) + NONCE)
3. Service Computes SHA256(StoredSaltedHash + NONCE), confirms that it matches what the user sent
4. If the two match, the user is authed.
An attacker cannot reuse what the client sent because the nonce is not reused, and he cannot fake the nonced hash because he does not know either the password or the StoredSaltedHash.
There's essentially rainbow tables computed for "123456"+RandomSalt iterating over salts. There are a bunch of them covering the most frequent passwords. Since you are using the same salt for the whole site, two users with the same password have the same StoredSaltedHash, so you order by number of repetitions, and the most frequent is likely one of those ("123456" tended to be the most popular the last time I checked). This exposes your salt and then it's game over.
What I'm trying to get across (and failing apparently) is that this is still vulnerable to lots of attacks, which means that you'll have to use HTTPS underneath all of this. Once you are doing all of this over a HTTPS connection, there's simply no point in doing it, you are just increasing the attack surface for no substantial gain in security.
This is only an issue if the hash can be reversed. The entire raison d'etre for salts is to prevent hash reversal via precomputed tables.
>There's essentially rainbow tables computed for "123456"+RandomSalt iterating over salts
Rainbow tables are already enormous-- in the hundreds of GB range for 9+ character passwords. Iterating over the range of possible salts makes the storage requirements untenable.
As long as you choose an unlikely or unique salt which could simply be your site's FQDN or its MD5 hash, this isn't an issue. No one is going to have a rainbow table for md5(yourFQDN.com) as salt.
>which means that you'll have to use HTTPS underneath all of this
You should but it is not necessary for secure password transmission. This is a solved problem for decades now.
>Once you are doing all of this over a HTTPS connection, there's simply no point in doing it, you are just increasing the attack surface for no substantial gain in security.
Layered security is a thing. Root CAs can be compromised, trusted CA stores can be tampered with, SSL busters like CRIME or BEAST can show up on the scene, someone can gain network access behind the SSL termination.... Layered security is why when LastPass got popped nothing of value was lost, because they used legit KDFs and salts.
There's no increase in attack surface for using an HMAC behind SSL. If SSL is your only line of defense, your security model is stuck in the 2000s.
If password is sent over HTTP in plaintext, then password can be used in a replay attack.
Of course you can also do a dozen other things with it, such as attack other sites.
And of course this flaw is trivially rectified by having the site send a nonce.
In other words you can combine salts + hashes + nonces to both eliminate the server's need to know the password and the possibility of a replay attack.
Recovering whatever the server has stored is typically going to be sufficient to authenticate the user, but storing it as a hash mitigates some threats.
Put plainly, nonces are countermeasures specifically for replay attacks and they work.
E.g., if your user-agent does it all for you, you could consider it trusted, but if all the code is provided by the "untrusted" service-provider that you won't want to see your password, it ends up just being for show.
Similar situation with ProtonMail: As long as you use the clients shipped by them (webmail, app), all of the security hinges on nothing but a promise. Their app can read the passwords and keys as much as it wants.
- open up private browsing
- press F12 (or however you get the developer console on a mac) and go to the networking tab
- go to gmail.com say
- enter your gmail credentials
- look at the post request generated, and at the request tab, it will contain your password in plain text
So passwords don't get hashed on transit, this is why having HTTPS is so crucial, which is to prevent someone in the middle (say when you connect to an open Starbucks wifi) from sniffing out your unencrypted password. The password on the server side initially can be unencrypted before it gets hashed to be stored into the database. So in this instance, the password in the database is hashed, but there is a small period where the password is plain text in memory.
For a site called hacker news, it's really sad how little people here know about hacking.