Is it worth hashing passwords on the client side

102,317

Solution 1

Basically, your friend is right. But simply hashing the password on the client side is only just better than submitting it as plain text to the server. Someone, who can listen for your plain text passwords is certainly also able to listen for hashed passwords, and use these captured hashes him/herself to authenticate against your server.

For this matter, more secure authentication protocols usually jump through a number of hoops in order to make sure, that such a replay attack cannot work, usually, by allowing the client to select a bunch of random bits, which are hashed along with the password, and also submitted in the clear to the server.

On the server:

  • generate a few bits of random
  • send these bits (in clear text) to the client

On the client:

  • generate a few random bits
  • concatenate password, the server's random bits and the client random bits
  • generate hash of the above
  • submit random bits(in clear text) and hash to the server

As the server knows its own random information as well as the client's random bits (it got them as clear text), it can perform essentially the same transformation. This protocol makes sure, that nobody listening in this conversation can use the information later to authenticate falsely using the information recorded (unless a very weak algorithm was used...), as long as both parties generate different "noise bits" each time, the hand shake is performed.

Edit All of this is error prone and tedious and somewhat hard to get right (read: secure). If ever possible, consider using authentication protocol implementations already written by knowledgeable people (unlike me! The above is only from memory of a book I read some time ago.) You really don't want to write this yourself usually.

Solution 2

First of all, this does NOT improve the security of your application (assuming it is a webapp).

Use SSL (Or actually TLS, which is commonly called SSL), its not really expensive (Measure the time you are using to find ways around it and multiply it with minimum wage, buying a certificate wins almost always).

The why to this is simple. TLS solves a problem (when used with bought certificates, not self signed) that is quite big in cryptography: How do I know the server I am talking to is the server I think I am talking to? TLS Certificates are a way of saying: "Me, the certificate authority, trusted by your browser, certifies that the website at [url] has this public key, with a corresponding private key, which (private key) only the server knows, look I signed my signature all over the document, if anyone altered it you can see".

Without TLS, any encryption becomes pointless, because if I sit next to you in a coffeeshop, I can make your laptop/smartphone think I am the server and MiTM (Man in The Middle) you. With TLS, your laptop/smartphone will scream "UNTRUSTED CONNECTION", because I don't have a certificate authority signed certificate that matches your site. (Encryption vs. Authentication).

Disclaimer: users tend to click right through these warnings: "Untrusted connection? What? I just want my pictures of kittens! Add Exception Click Confirm Click YAY! Kittens!"

However, if you really do not want to buy a certificate, still DO implement client side javascript hashing (and use the standford library (SJCL) for that, NEVER IMPLEMENT CRYPTO YOURSELF).

Why? Password reuse! I can steal your session cookie (which allows me to pretend to your server that I am you) without HTTPS easily (see firesheep). However if you add a javascript to your login page which, before sending, hashes your password (use SHA256, or even better, use SHA256, send them a public key you generated and then encrypt hashed the password with that, you cannot use a salt with this), and then sends the hashed/encrypted password to the server. REHASH the hash on your server with a salt and compare that to what is stored in your database (store the password like this:

(SHA256(SHA256(password)+salt))

(save the salt as plaintext in the database as well)). And send your password like this:

RSA_With_Public_Key(SHA256(password))

and check your password like this:

if SHA256(RSA_With_Private_Key(SHA256(sent_password))+salt_for_username) == stored_pass: login = ok

Because, IF someone is sniffing your client, they will be able to login as your client (session hijacking) but they will NEVER see the plaintext password (unless they alter your javascript, however, a starbucks hacker will probably not know howto/be interested in this.) So they will gain access to your webapp, but not to their email/facebook/etc. (for which your users will likely use the same password). (The email address will either be their loginname or will be found in their profile/settings on your webapp).

Solution 3

You're likely OK not to worry about this - as Dirk mentions even if you hash the passwords a malicious user could be on a network and see the hash get sent, and could simply send the same hash themselves.

It is slightly better, in that it prevents the malicious user from knowing what the password is, but since they can still log in (or potentially reconstruct the original password), that's not that helpful.

In general, if you're concerned about the safety of your user's passwords and data (and you should be!), you'll want to use a secure SSL server. If this isn't a concern for you for whatever reason you might as well not bother with hashing; it's just security through obscurity.


Edit Aug 2014: Google is pushing more and more strongly for websites to switch to HTTPS everywhere, because securing the communication itself is the only way to prevent network sniffing attacks. Attempts at obfuscating the data transmitted will only hinder, not stop, a dedicated attacker, and can give developers a dangerous false sense of security.

Solution 4

Actually I disagree that client side hashing is more secure in this case. I think it's less secure.

The entire point of storing a hash of the password in your database as opposed to the real password (or even an encrypted password) is that it is mathematically impossible to obtain the original password from a hash (although it is theoretically possible to obtain a colliding hash input, the difficulty of which depends on the security strength of the hashing algorithm). The possible attack vector here is that if a potential attacker somehow compromised your password storage database, he/she still would not be able to obtain the original passwords of your users.

If your authentication mechanism sends a hash of the password, then in this security breach scenario, the attacker does not need to know the real password - they just send the hash that they have and hey presto, they have access to a particular user's account, and by extension, your entire system. This completely defeats the point of storing a hashed password in the first place!

The really secure way to do it is to send the client a one-time public key for them to encrypt the password, then you decrypt and re-hash it on the server-side.

By the way, this kind of question will probably get more expert responses over on Security StackExchange.

Solution 5

Note that keeping passwords secure against third parties parties is not all there is to it.

As soon as privacy is involved (and when ever is it not, these days?) you don't want to know the password. You can't abuse or leak what you don't have, so both you and your clients can sleep better if you never ever see their clear-text passwords.

Therefore, hashing/encrypting client-side makes sense.

Share:
102,317

Related videos on Youtube

Zakaria
Author by

Zakaria

Updated on April 06, 2020

Comments

  • Zakaria
    Zakaria about 4 years

    When I want to put a login system in place, I always compare the MD5 of the given password with its value in the users table on the server side.

    However, a friend of mine told me that a "clear" password could be sniffed by a network software.

    So my question is: is it a good idea to hash the password on the client side? Is it better than hashing it on the server side?

    • Cyclone
      Cyclone over 11 years
      I was thinking of hashing the password on the client side, but only just so I can rest assured the client's password never exists as clear text on the server side, meaning they can feel easier knowing that I don't know their actual password, or can't easily give it up if compromised. am I crazy?
    • Teejay
      Teejay about 8 years
      @Cyclone Hashing ONLY at client-side is definitely a bad idea, since if the attacker somehow knows the hash, he can use it to login as if he knew the password, bypassing the client-side hashing code.
    • MSalters
      MSalters about 8 years
      @Teejay: That's why you don't send the hash in the clear. The server sends a random salt to the client, you append the password hash, and hash the whole thing again, then send that back to the server which does the same calculation. A replay attack fails because the salt will be different
    • efr4k
      efr4k almost 8 years
      Shouldn't this question be over at security.stackexchange.com?
  • Zakaria
    Zakaria over 13 years
    How can he authenticate with the hashed password in the login system since it will be hashed again?
  • Dirk
    Dirk over 13 years
    If you store your passwords in hashed form on the server (as you should) then the client will have to hash the password twice: first, the password alone, so it matches with the server's view of the world, and then as described above for the protocol's sake.
  • Pacerier
    Pacerier almost 12 years
    @Dirk, since the attacker can sniff both ways, the "random bits" would be sniffed along. Then the attacker can analyze (read: brute force) the request and response pair offline to find the original password.
  • Dirk
    Dirk almost 12 years
    @Parcerier, yes, of course. But that's not the point here. The same can be said about any kind of password hashing scheme (salting vs. rainbow tables, etc.) The random noise is added to make reply attacks hard (as in: it's hopefully too expensive to break using brute force), but cannot render them impossible.
  • AaronLS
    AaronLS about 10 years
    "concatenate password, the server's random bits and the client random bits" should read "concatenate password hash," if your goal is to store the password in its hash form on server and combine it with this protocol
  • AaronLS
    AaronLS about 10 years
    However, for the purpose of submitting a password or the hash of a password, often an asymmetric process like Diffie-Hellman is used to establish an encryption key that allows both sides to exchange information without a snooping party being able to decrypt it. This is exactly what SSL does, and is the reason that most sites have their login page on HTTPS/SSL. SSL already protects against replay attacks. I would recommend leveraging SSL rather than building your own protocol. Although I do agree with salting+hashing the password client side, but send these across an established SSL connection.
  • AaronLS
    AaronLS about 10 years
    It is not that the process above is clearly flawed, but it is better to use an established public protocol that has been thoroughly reviewed and vetted, then to try and build your own and risk a mistake that will compromise your site. Properly deployed SSL will protect against a wide variety of other attacks as well.
  • James Wright
    James Wright almost 9 years
    Completely agree with this. For a client-side approach to work one would also have to send the salt to the client, which would invalidate the whole purpose of salting!
  • aidan
    aidan over 8 years
    Just to be clear: if you're not using HTTPS, it doesn't matter what javascript you run on the client; a MITM would be able to modify the contents of your page before it hits the client. HTTPS is the only solution.
  • Kuba Wyrostek
    Kuba Wyrostek over 8 years
    A question for clarification: using this schema is only possible if passwords are stored server-side without salt, right? When salt is used, client would need to know the salt before hashing the password with random bytes. And allowing client to obtain salt from server is a security risk? Or is it not much of a risk (provided that I somehow manage to create permanent fake salts for non-existing users)?
  • Eric Grange
    Eric Grange over 7 years
    Note that while HTTPS is fine as a protection for real-time highjacking, it is not against an attack on logs, be they server-side debug logs, or the "transparent proxy" logs that companies are legally required to maintain in most countries. Sending passwords in clear exposes them whenever those logs will be leaked (either through negligence or after having been requested for a legal investigation)
  • MSalters
    MSalters almost 7 years
    @JamesWright: The point is sending a random salt for each use, which prevents the illegal reuse of login messages. (A form of replay attacks). Sending the same salt every time is indeed pointless.
  • Dan
    Dan almost 6 years
    Exactly my concern. If the server somehow logs by accident due to poor implementation or malicious intent, then it's possible that other account of the user can be compromised if they reuse passwords.
  • f1lt3r
    f1lt3r over 5 years
    Agreed! A lot of people miss this point. If I download your password database of salted hashed passwords, and I can crack just one using a hash lookup database, then chances are I can crack them all. Once I have 50k original passwords, I now have the key to x users on n services that only encrypt on the server. If each service uniquely hashes the password before it leaves the client, the large database of cross-service passwords gets much, much smaller. Check your AWS login traffic, see what they do. It's probability my dear Watson.
  • f1lt3r
    f1lt3r over 5 years
    I think your opinion that clientside hashing is only "slightly better" is true if you are solely focused on getting x user's password and accessing a single service. If you consider the collective effect, I would say it's "much better"; because it prevents building large lookup databases of passwords used to brute force salted hashes across multiple services. IMO. See what AWS Cognito does in the client for reference.
  • Neyt
    Neyt over 5 years
    I thinks this is a good answer but it probably needs some more informations on how to salt properly and that it is better to use a "slow" hashing function before storing the password on server (like bcrypt).
  • damianostre
    damianostre almost 5 years
    What you need to do is use a "nonce" (en.wikipedia.org/wiki/Cryptographic_nonce). That way, the server also controls the salt and makes this secure. Hashing on the client side is also important so that injected JS code can't easily find it later. More here: stackoverflow.com/a/21716654/43615
  • damianostre
    damianostre almost 5 years
    For using salt+nonce in a login authentication process, see this answer: stackoverflow.com/a/24978909/43615
  • damianostre
    damianostre almost 5 years
    To prevent replay attacks where the attacker re-uses a previously used hash+salt, add a nonce. For using salt+nonce in a login authentication process, see this answer: stackoverflow.com/a/24978909/43615
  • Daniel Methner
    Daniel Methner about 4 years
    Obviously if you hash it on the client side, you will have to hash it again on the server side to prevent the point you are making. As others point out though, for privacy you want a client side encryption already.
  • user1034912
    user1034912 almost 4 years
    Sending a One time public key... isn't this what SSL does??
  • Adam Burley
    Adam Burley almost 4 years
    @user1034912 yes true, but I assumed the OP does not only want to rely on SSL for security. Some networks, especially corporate ones, have SSL terminate at some load balancer, meaning the plaintext password is visible to network components other than the serving application. Generally we use client-side encryption to avoid this and ensure e2e encryption between the client and the serving application.
  • T. Salim
    T. Salim over 3 years
    Yes, instead of using SHA256 directly, use bcrypt or even the more secure argon2 implementation.
  • S To
    S To about 3 years
    Client side hashing is not pointless. You need to think about millions of user's privacy, not just one. I don't understand why people would think a hacker is able to intercept millions of people's secured connection at once to the server providing their hashed passwords. This is not just practically possible. Even if it is possible they would be smart enough to access the servers alone that hashes the user's cleartext password and can now see the hashed password and use it against the server. It makes no difference of hash or not at client side. But hashing on client side is far more safer.
  • S To
    S To about 3 years
    I completely agree, hashing on client side is much more logical for many reasons. If a hacker wants to know the actual hashed password, they're going to have a hard time figuring it out. It's just completely foolish and straight up dumb sending clear text passwords over "secured" connection. There is not such thing as a "secured" connection in the hacking world. Hashing the user's password on the user side can bring new security algorithms which will be extremely difficult for hackers to seem they are the actual user by tripping detection from the server.
  • stewSquared
    stewSquared over 2 years
    In 2021, you essentially encrypt the password client-side (with TLS), and hash server-side to prevent an attacker being able to authenticate as users in case a record is leaked containing a user's login info. @STo breaking TLS isn't typically how hashes are leaked. More common is a data breach, where data at rest, not in transit, is leaked (eg., SQL injection, buffer overflow, data at exposed to the internet, rogue employee, stolen admin credentials). This doesn't mean keeping passwords client-side is pointless (eg., 1password and protonmail), it just doesn't obviate the need for server hash.
  • stewSquared
    stewSquared over 2 years
    If you were authenticating with a hash generated from the password client-side, you wouldn't want to see that in the logs either.
  • Kfir Eichenblat
    Kfir Eichenblat over 2 years
    I'm late to the party, but building on @f1lt3r 's answer, I would like to shed some light on the fact that users often use the same password for multiple services, or at least have a clear pattern. Personally I have chosen to hash passwords on the client side in the past just to reassure my users that my server / myself do not know what their password is

Related