I used client side password hashing in my register and login project.

Its purpose is to prevent passive adversaries/eavesdroppers from discovering users' plaintext passwords when HTTP requests are in transit.

But still an attacker can perform a brute-force attack against the hash; And i think most or at least many passwords will be discovered this way, because they are too weak to resist against powerful brute-force attacks.

So I recently thought of using asymmetric encryption.

Passwords will be encrypted with a public key on the client side (with randomized padding to make brute-force attacks impossible).

Is this a good idea?

Is it worth its costs?

Do u know about any problems regarding such a scheme?

Any related info is appreciated.

  • 2
    Why not https and server side password validation?
    – user93353
    Apr 28, 2013 at 9:32

2 Answers 2


Firstly, I'm assuming that you're doing this to weaken man in the middle attacks (which really are the only problem when it comes to plaintext passwords over insecure HTTP)

Client side hashing has little to no benefit. An attacker, on picking up the hash will not need to brute force the hash. All your server needs is the hash, so the attacker can simply craft a POST request with the hash in it and send it over. One doesn't need the plaintext to get in to the system.

Regarding your solution:

If you're using the same public key for all clients, then the situation is effectively the same. As an attacker all I need to sniff is the ciphertext you send over, and I can impersonate you by sending the same ciphertext.

What if you gave different public keys to each client on each login? Then I could launch a man in the middle attack where I swap the server's public key with my own, decrypt the ciphertext you send (this getting your plaintext, even better), and encrypt it with the server's public key.

There has got to be a way for the client to know which public key is correct. For that you'd need some kind of trust system. Where clients know which public keys correspond to which server. But that will lead to millions of public keys being stored in browsers. So you'd need some sort of certificate chaining system. And I think you realize where I'm going with this ;-)

TL;DR: Use HTTPS, client side encryption without a trust system is not any more secure than no encryption at all.

If you're worried about shared passwords on other sites being detected after breaking the hash, then both hashing and public key encryption are fine (public key encryption is better due to rainbow tables). Note that these will only foil the plans of a passive attacker. If the attacker mounts an active MITM attack, then they can change the JS code that you send and remove the encryption bits entirely.

  • the reason i want to protect password is the same reason why we don't store plaintext password on the server side and use a hash instead. the benefit of that hash is for when the system is already compromised (at least to some extent); we want to limit the potential damages that can be done. e.g. plaintext passwords can be used to attack the other (not compromised) accounts of users. likewise, i want to limit the damage from passive adversaries/eavesdroppers when the requests are in transit over insecure channels. i think not all attackers are or can be active (always).
    – H M
    Apr 28, 2013 at 10:17
  • @HM: As an attacker, I can just modify the JS code you send over to not encrypt the password. That's not hard, and I'll be able to sniff the plaintext. Apr 28, 2013 at 10:23
  • Anything you do on the client side can be spoofed. IIRC on a network if someone can read your communications, they can modify them as well (cf ARP spoofing et al) Apr 28, 2013 at 10:25
  • please read my comment carefully. i said protection against passive attackers only. are all attackers always active and can they be?
    – H M
    Apr 28, 2013 at 10:26
  • 1
    @HM: See edit, I've updated to include this. However, if I were an attacker, I would inject a keylogger script in every page I attack that sends me data entered into a username/password field. And that would bypasss most client side encryption. Apr 28, 2013 at 10:58

This is what I understand from your question.

  • You accept a password at the client side
  • You random pad the password.
  • You hash the password at the client.
  • You encrypt the hash using the public key of the server
  • You send the encrypted hash to the server
  • Server decrypts the hash using it's private key & compares it against it's stored hash to check the validity.

The problem here is a replay attack. Anyone who eavesdrops the encrypted hash can reuse it.

The solution to this can be

  1. Add the current time to the password at the client side. Then hash it. When the server decrypts what it gets - it first splits the package into password hash & time. Only if the time is within +- delta of the current time, it checks the password. This will disallow reusing the eavesdropped encrypted hash unless it's used very quickly.
  2. Take the above scheme and also add a ID number to the password + time string. And then hash etc. Server's responsibility is to make sure a particular ID number is not reused for a particular client on the same day. Client's responsibility is to make sure it doesn't reuse the same ID number on the same day. This will prevent a replay attack even if done very shortly after the event.

One very important component here is that the server's certificate (public key) has to be pre-installed on the client - it shouldn't be that the client gets the certificate by requesting it from the server.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .