Password Encryption at Client Side

Is it worth hashing passwords on the client side

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.

Clientside password hashing

It 100% makes sense: in fact, the concept has been proposed by a number of people, but the difficulty is in implementing correctly. There are a number of pitfalls if you do it wrong, the most direct one is being vulnerable to "pass-the-hash" as @swa66 describes. To prevent that, you need to hash on both sides. The client-side hash should be slow (bcrypt, scrypt, argon2, or pbkdf2) whereas the server side hash should be fast (sha256).

EDIT: A number of people have down-voted this without understanding how this works, so I now include the basic details here (previously I only linked to how this works). The idea is to apply a slow hash such as bcrypt on the client side, and then a fast hash such as SHA256 on the server side. The fast hash is required to prevent pass-the-hash attacks. In the event of the database leak, an attacker either hash to invert the fast hash (impossible -- violates the one-way property of a cryptographic hash function), or brute force the preimage to the fast hash (impossible -- the size is the length of the output from the slow hash, for example 184-bits for bcrypt), or brute force the combination of the slow hash and the fast hash -- which puts the attacker back at the same position as if the entire computation had happened server side. So we have not reduced the security of password attacks in the event of a database leak by shifting the heavy computation to the client side.

I've surveyed a number of proposals like this in Method to protect passwords in databases for web applications. Additionally, I analyse the pros and cons and identify weaknesses that have not been identified before (account enumeration), and propose a unique way of doing this securely. The research is built off a number of sources, including:

  • Secure authentication: partial client-side key stretching… please review/criticize my idea
  • How to securely hash passwords? -- see section on Client Side Hashing
  • Client side password hashing
  • Discussion from various authors on Hacker News -- see comments from oleganza, mschuster91, crusso, etc...

You cite the Twitter example, and GitHub did similarly. When I wrote the paper above, the most prominent example for preventing a server from seeing the clear text passwords was Heartbleed, which I comment on in the paper (bottom of Section 1.3).

There has been subsequent follow up research by others identifying similar ideas -- Example: Client-Plus-Server Password Hashing as a Potential Way to Improve Security Against Brute Force Attacks without Overloading the Server. No one person deserves all the credit, but the main takeaway is yes it is a good idea if you do it securely, but you really need to understand the risks (it is easy to do insecurely if you have not read the research).

I STILL think hashing password on client side is better. Am I wrong?

If you think hashing BOTH client AND server side with a modern password hashing algorithm like PBKDF2, BCrypt, SCrypt, or Argon2 with a high work factor/iteration count is better, then I agree.

If you think hashing ONLY client side is better, then I have serious reservations about your threat model.

There are threats that hashing passwords server-side protects against, and threats that client-side protects against; here's a brief list:

  • BOTH: leaked password database entries allowing viewers to see what the user typed in cleartext.
  • CLIENT: Server-side insiders with packet/traffic interception access seeing what the user typed in directly

    • This is one of the two major threats that client side hashing IN ADDITION to server side hashing is a good fit for mitigating.
  • SERVER: Insiders with database access fradulently impersonating actual users

    • if passwords are ONLY hashed client side, then whatever's in the server DB can be fed to the system via the client request to log in as the user "legitimately" according to the server. This makes all server audit logs of who did what suspect.
    • if passwords are hashed server side, regardless of what happened client side, what is in the server does NOT authenticate the user if fed in via the normal authentication channel.
  • CLIENT: MitM attacks seeing what the user actually typed in

    • This is the other major threats that client side hashing IN ADDITION to server side hashing is a good fit for mitigating.
    • MitM attacks can come from the client's corporate IT department, a network provider or other ISP, the server organization's IT department (load balancers or advanced security appliances with the actual cert key, etc.), or many other sources.
  • NEITHER: MitM attackers fradulently impersonating actual users

    • No matter whether you hash it client side or not, what gets sent over the network to the server app IS what the server uses to authenticate you.

How to apply client side password encryption in laravel

This is exactly what HTTPS is for :)

How can I secure a password from the client side? Is it needed or HTTPS/SSL will suffice?

I would say A valid SSL certificate is Enough.

the client side hash should be treated as if it was the user's direct
password. It provides no more or no less security on the server than
if the user had directly given their password and should be protected
as such.
more info...

Should I hash the password before sending it to the server side?

This is an old question, but I felt the need to provide my opinion on this important matter. There is so much misinformation here

The OP never mentioned sending the password in clear over HTTP - only HTTPS, yet many seem to be responding to the question of sending a password over HTTP for some reason. That said:

I believe passwords should never be retained (let alone transmitted) in plain text. That means not kept on disk, or even in memory.

People responding here seem to think HTTPS is a silver bullet, which it is not. It certainly helps greatly however, and should be used in any authenticated session.

There is really no need to know what an original password is. All that is required is a reliable way to generate (and reliably re-generate) an authentication "key" based on the original text chosen by the user. In an ideal world this text should immediately generate a "key" by salting then irreversibly hashing it using an intentionally slow hash-algorithm (like bcrypt, to prevent Brute-force). Said salt should be unique to the user credential being generated.
This "key" will be what your systems use as a password. This way if your systems ever get compromised in the future, these credentials will only ever be useful against your own organisation, and nowhere else where the user has been lazy and used the same password.

So we have a key. Now we need to clean up any trace of the password on the clients device.

Next we need to get that key to your systems. You should never transmit a key or password "in the clear". Not even over HTTPS. HTTPS is not impenetrable. In fact, many organisations can become a trusted MITM - not from an attack perspective, but to perform inspections on the traffic to implement their own security policies. This weakens HTTPS, and it is not the only way it happens (such as redirects to HTTP MITM attacks for example). Never assume it is secure.

To get around this, we encrypt the key with a once off nonce.

This nonce is unique for every submission of a key to your systems - even for the same credential during the same session if you need to send it multiple times. You can reverse said nonce (decrypt), once it arrives in your own systems to recover the authentication key, and authenticate the request.

At this point I would irreversibly hash it one last time before it is permanently stored in your own systems. That way you can share the credential's salt with partner organisations for the purposes of SSO and the like, whilst being able to prove your own organisation cannot impersonate the user. The best part of this approach is you are never sharing anything generated by the user without their authorisation.

Do more research, as there is more to it than even I have divulged, but if you want to provide true security to your users, I think this method is currently the most complete response here.


Securely hash passwords, irreversibly, with a unique salt per password. Do this on the client - do not transmit their actual password. Transmitting the users original password to your servers is never "OK" or "Fine". Clean up any trace of the original password.
Use a nonce regardless of HTTP/HTTPS. It is much more secure on many levels. (Answer to OP).

Related Topics

Leave a reply