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

Passwords can be hashed directly client-side with javascript, which is way more secure than sending them clear on the wire, so i dont disagree with Google's stance here and dont understand the hate



Hashing passwords client side has no benefit if a site uses HTTPS.

If a site uses HTTP, then hashing the password client-side and sending it up to the server is equivalent to sending a clear text password. If an attacker can already read your traffic, what is stopping them from using your password's hash to log-in to your account?


It stops them from using the password to log in to your other accounts.

It stops a compromised server from silently leaking unhashed passwords.

It makes password hashing user auditable.

You could even do a call and response model to stop the hashed password to log in at all. Here is a primitive scheme for such a model (public key crypto probably enables more clever schemes, not sure):

- Upon signup, generate hashes of "$password$site$i" for i in 1 to 1000. Send these to the server and have the server hash them again.

- Upon login, after the user has entered their password into the box, send an integer from i from 1 to 1000 to the browser, have the browser send back the hash of "$password$site$i".

Now a compromised hash can only let you log in 1 time in 1000. Combine that fact with the other available signals for "is this who we think it is" and you should be able to reject people who stole the hash reasonably reliably. Meanwhile since you are still hashing the password on the server (again) you have lost literally nothing but a tiny bit of computation time.


Use a password manager and don't reuse passwords. If your randomly generated, unique password has good enough entropy then why go through all of the trouble of the rest of the client side hashing?

There's nothing stopping you from hashing your own passwords client side and sending your bcrypt hash up to the server except some sites still truncate the passwords to 32/16 chars etc.

When you have the need for the level of security, client side hashing will not be as good as dedicated HSMs that many services now use on authentication.

Writing your own crypto flows can be extremely dangerous as you open yourself to all kinds of side channel attacks.


A password manager is a client side method that only works for people who opt into it, Google needs to deploy a server side method. Likewise with hashing my own passwords client side. HSMs.

As for writing my own crypto. Indeed, if anyone actually used the scheme I suggested they would be making a mistake. I wrote it not to be used but to demonstrate that we can do better in an easy to understand way. Unlike me, Google has the resources to read the papers, do the math, carefully implement this, and do it properly.

Keywords for how to do it properly include "zero knowledge password proof" and "password authenticate key exchange".

PS. It's irrelevant to this conversation, but putting all my passwords into one program has always struck me as a monumentally stupid idea. I use one for passwords I don't care about, I memorize unique passwords for passwords I do care about.


worshipping an arbitrarily contrived measure of password entropy makes for good security theatre, but there's a lot that goes into maintaining anything resembling actual security. How many people use "password generators" and trust that they'll come up with "random" words? What about that old saying about putting eggs in a basket?


> It stops a compromised server from silently leaking unhashed passwords

If you trust the site to deploy correct JavaScript to do this, then that's the same level of trust that they implemented password salting and hashing server side. You don't gain any robustness by moving this to JavaScript.

Your scheme is just a weak salting technique. You'd be better off with just using a longer salt and hash function.


I separately assume a salt is part of my hash function. Salts only help with rainbow tables (an admirable goal, but not my one here).

I can trust the site to deploy the correct javascript more than I can trust it not to steal passwords because

- That is auditable - it is impossible for a malicious site to do so without risking being caught.

- The HTML/JS can be served from static cloud storage that is far less likely to be hacked than the server running a DB verifying passwords.


> - That is auditable - it is impossible for a malicious site to do so without risking being caught.

Hardly. Minimization and obfuscation is trivial, and you can ensure the output is always different in order to defeat auditing. Not great for caching obviously, but 'auditability' is not achievable if the server is determined to fool you.

> - The HTML/JS can be served from static cloud storage that is far less likely to be hacked than the server running a DB verifying passwords.

Password are simply not where you want to leverage your security. If you can find a document example of a real threat that this approach would have mitigated, then I'll take it seriously.


So the malicious site can run risk assessment first and then if it thinks nobody's looking, send different code for hashing to this particular user.


This still feels vulnerable to XSS. Better would be to have browsers provide an API to do this so that $site is trusted.

The downside is not a tiny bit of computation time. It's also increased latency for the customer.


This is completely wrong. HTTPS is what secures this, not client side password hashing. If you don't use HTTPS, you can just get MITM'd to disable any kind of client side hashing.


You are wrong. Client-side hashing CAN be a silly thing, but it can also prevent a (compromised) server from seeing your password which you probably use on other websites (which is what most people do unfortunately).


>but it can also prevent a (compromised) server from seeing your password

If the server is compromised, then there is no protection of your cleartext password at all. This is because the entity that compromised the server can replace the original JS with anything, including new JS that sends your cleartext password off to their own host as you type each character.

The only activity on your part that can save you against comprimised servers is having a unique password per server (i.e., not reusing any passwords).


Not true in modern architectures, that situation only applies to more traditional file & api server combo's. If you statically serve your site with a service like s3 and have a backend running on lambda or ec2 - the attacker cannot modify the static assets and the client side hashing will prevent them from seeing the plaintext password.


Again, this is wrong depending on how the client is implemented, if updates are signed, if we are talking about a protocol, etc.


and if said "compromised" server simply decides to not supply the js that hashes the password?


Thanks for saying it. Client-side scripting can't protect against a compromised server when the client scripts are provided by that same server.


The answer is that it depends. We could be talking about protected js with SRI, signed updates with an electron client, a browser plugin or native hashing, a protocol similar to SSH that hashes the client pw, etc.


This is only true when client-side hashing is under control of the client. In a web browser, it is not. The browser will happily run whatever JS the server sends it. So if the server is compromised, it can send compromised JS, and there goes your client-side hashing protections.

An example of where it might work is in an app, where you're getting the client code from a separate channel like an app store.


It can protect you against non-malicious issues on server-side. If I recall correctly, twitter recently discovered that they were logging passwords in plaintext by accident. With hashed password you reduce exposure of actual passwords in this type of situation.


or a separate channel like another server - which is the standard in every large web application I've ever seen.


This is why server side HSMs (hardware security modules) are a thing.


Is this true? Over time I have seen user passwords end up in a variety of strange internal places accidentally, like log files or crash dumps.


See: https://blog.cryptographyengineering.com/2018/10/19/lets-tal...

About client side benefits. I'm not advocating for JS in the browser but there are benefits to doing some work client side.


Who is sending passwords in cleartext on the wire?


I think totony meant sending passwords without pre-hashing, but yeah it doesn't make sense to send any confidential information in clear text that should be sent via E2E encrypted TLS channels.

Furthermore, pre-hashing doesn't necessarily make transmitting confidential information safer, as one would argue that your client side javascript can be reverse-engineered and give the attacker more information about how you hash your data.


Really your back end should just treat password's hashed just like any password.

Ideally, if TLS was being MITMed somehow such as a dodgy root cert. It would shield the users plaintext password so it could not be used to login into other services. The problem is as soon there is TLS issue an attacker can modify the Js to just send the password in the clear. It really would require code that can't be modified by attacker. This means that there would have to be some sort of browser support. Otherwise it does nothing against the attack it would protect against.

The main benefit is offloading some computation workload on the clients machine. This could allow you to increase the work load required to brute force the password hashes assuming your database leaks. (aka increase iterations or memory requirements)

You last argument is security through obscurity if exposing how you hash makes it easier to brute force the passwords your password hashing sucks.


Yes I meant sending the password cleartext inside the transport protocol*

pre-hashing doesn't prevent an attacker from stealing your account if it can read the communication, but it prevents it from having your password and using it everywhere else where you might re-use the password or a permutation of it


Almost any http site with a login form is sending your password in cleartext. Thankfully, initiatives like Let's Encrypt have made plain http sites much less common than they used to be.

Hashing the password before sending it doesn't really help you much - the naïve approach is vulnerable to "pass-the-hash" (where you basically send the hash instead of the password as the authentication token). The secure approach involves either some kind of challenge-response or a nonce salt, but these aren't as easy to implement correctly.


Indeed. And: who is hashing passwords on the client? As this would require either not using a salted hash, or sharing the server's salt with the client, in order to obtain identical hash values for comparison. In either case that system's entire password inventory would be a lot more vulnerable.

TLDR don't do that, send passwords over SSL and use a good password hashing algorithm on the server like BCrypt.


Yep. Proper password hashing requires per-credential salt, pepper (for all credentials) and a strong algorithm (IV, iterations etc.) Revealing all those information is a leak and arguably making client side hashing less secure (by giving away a lot of parameters for attackers to attack)


NIST may say that you should use "peppers" for passwords, but nobody else does.

None of bcrypt, scrypt, or Argon2 use them and are not materially worse for it.


Yes, adding pepper is a recommendation not a mandatory step. But a lot of sites do, I.E. PagerDuty [1], paired with PBKDF2 as many apps requires to meet FIPS certification or enterprise support on many platforms.[2]

[1]: https://sudo.pagerduty.com/for_engineers/

[2]: https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet


Salts are not meant to be secret, nor are the hashing functions. You gain little by hiding them


if you're in the position to or are developing an app use argon2!


Judging by his comment, totony is.

Your password _is_ whatever you send over the wire. Doing a hash in JavaScript before sending it won't obscure the user's password from anyone who can see their traffic; it will obscure the user's password from the user.


Nope, the password is what people type in. They may type the same things at many websites. We should not care what that exactly is.

Why would you want to see actual user password if you can just not see it?

If you see a password you can leak it by screwing up in numbers of ways. If you never see a password you just can't leak it.

E.g. Twitter recently discovered that they were storing passwords in plaintext in logs, GitHub had similar issue.

Take a look here: https://arstechnica.com/information-technology/2018/05/twitt....

Of course, a hash that you will receive from client should be treated as a normal password including all good practices.


No, the password is whatever you send over the wire. If a website processes your attempt to type "password" into "5f4dcc3b5aa765d61d8327deb882cf99" before sending that to the server, then your password for that website is 5f4dcc3b5aa765d61d8327deb882cf99. That's what the server sees and how it recognizes you. The only effect of this is to make it less likely that the user knows his own password.


If user password is "passsword" he may be reusing it across 50 other websites. If you leak information that "password" is linked to "email@gmail.com" I can hack the 50 other websites. If you never knew that the user password is "password" you can not leak it and I can not use it to log in into 50 other websites. Leaking "5f4dcc3b5aa765d61d8327deb882cf99" is useless to hackers, because he cant go and use it to login into another website.

So, there are properties that differentiate "password" and "5f4dcc3b5aa765d61d8327deb882cf99", even if for the server it's all the same.


The distinction you're trying to draw vanishes as soon as this becomes a standard practice. Passwords are already stored hashed and salted. They get compromised anyway, because the data is valuable. Under the circumstances you describe, cracking 5f4dcc3b5aa765d61d8327deb882cf99 (which takes less than a second) is just as valuable as cracking a password database entry is now, because the underlying issue -- reuse of credentials -- hasn't gone away. (In fact, you're encouraging it, so it's probably somewhat worse.) As long as people are reusing credentials across multiple websites, those credentials will have value greater than that associated with their use on any particular site, and other people will put in the effort to crack them. Even when you're generating and submitting a cryptographically secure salted hash, you haven't improved on the situation now, where databases store a secure salted hash of the password.


Lots. But even those that don’t tend to send the password to the server, which is still bad.


How is sending the password to the server over HTTPS bad? What would you do otherwise? Hash it on the client? So are you not using salted hashes for your password store? That's far worse. Or you're hashing twice, the first with no salt client-side, then again with salt on the server side, which is fine, but the client-generated hash must be unsalted so is basically just the password itself: steal the client-generated hash instead of the original password, just as good with only minor loss in value (might not be able to reuse it on other sites for the victim; but actually maybe still could if you can build a reverse index of common passwords hashed using whatever algo is in use.)

And if you don't trust HTTPS to protect sensitive information, why would you send the auth cookies over it that have virtually as much power the password that was given in exchange for them in the first place?


Why would you want to see actual user password if you can not see it?

If you see a password you can leak it by screwing up in numbers of ways. If you never see a password you just can't leak it.

E.g. Twitter recently discovered that they were storing passwords in plaintext in logs, GitHub had similar issue.

Take a look here: https://arstechnica.com/information-technology/2018/05/twitt...

Of course, a hash that you will recive from client should be treated as a normal password including all good practices.


> Hash it on the client? So are you not using salted hashes for your password store?

There is no reason you can't also salt on the client. Salts do not need to be secret. The substantial constraint you outlined in your comment isn't a problem.


Literally almost everyone. (Wrapped in a TLS connection of course.)


> (Wrapped in a TLS connection of course.)

So, not cleartext over the wire then.


If the client hashes the password then the hash itself is the password. Meaning stealing the hashes passwords is the same as stealing the plain text password for which they're based, since you can post them direct.

Blizzard entertainment does half client half server hashing which is rather clever, one of the few examples where client hashing makes sense.


Nope, the password is what people type in. They may type the same things at many websites. We should not care what that exactly is.

Why would you want to see actual user password if you can just not see it?

If you see a password you can leak it by screwing up in numbers of ways. If you never see a password you just can't leak it.

E.g. Twitter recently discovered that they were storing passwords in plaintext in logs, GitHub had similar issue.

Take a look here: https://arstechnica.com/information-technology/2018/05/twitt....

Of course, a hash that you will receive from client should be treated as a normal password including all good practices.


I'm curious, how is half-hashing the password different from really hashing it?

The best protocol I know of is to derive a signing keypair from your (salted, stretched) password, and store the public key on the server instead of a password hash. Then during login, the server sends a challenge to the client, and the client signs it. The server never sees any secret material at all. Keybase uses a version of this protocol.

Unfortunately all the magical client side crypto in the world doesn't save you if the attacker can compromise your server and then send clients bad JS :p


Have you heard of this new technique called HTTPS?




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

Search: