Putting aside that it may sound paranoid.

I know that many users tend to use the same password on many sites. Then, from an ethical point of view, I should not only be concerned about security breaks that affect my own system, but also how my system might facilitate breaking the security of other systems.

Suppose that an attack allows a third party to read (but not modify1) the communication, including the password exchange during login. If they can read the user's name and password, they could gain access to the account of that person on other systems if they used the same name and password there.

To avoid that, I was thinking about doing hash(system_public_pepper+username_as_salt+password) at client side, along with bcrypt (which includes salt) with a secret system pepper. Both peppers would change at each server (randomly generated on install).

But then my new concern is whether this client-side hash could weaken the password (example: limiting the entropy).

And then:

  1. What hash should I use to make sure there is no significant entropy loss? Is MD5 ok?
  2. Can the pepper and/or salt weaken the entropy, considering it is of public knowledge (although salt changes between users)?
  3. Does it make a difference whether the salt (username) or pepper (public) are prepended or postpended? Which order is best?

    I think that if the salt or pepper are prepended, one can take the state of the hash algorithm at that point as a start, and then computing the hash of every password would cost less (as if there were no salt and pepper).

    But, also, one could apply the same to common passwords if they are at the beginning.

    1. Is there anything else I should consider?

Edit: I think that there is a misunderstanding from what I proposed. So, I will put an example. U is user, C is cliente, S is server, D is database (just pseudo for clarity, we can use PDO for prepared statements and so).


C>S: I need to signup, send me the public pepper.
S>C: {"system_public_pepper":"Potts"}
U>C: {"username":"johndoe","password":"IWasBornOn1987"}
C: P=system_public_pepper+username+password; //P="PottsjohndowIWasBornOn1987"
C: H=md5(P); //="28d36f3969e05dedb5f9ba20acd3842a"²
C>S: {"username":"johndoe","hashpass":"28d36f3969e05dedb5f9ba20acd3842a"}
S: private_pepper="GwynethPaltrow";
S: new_pwd=private_pepper+hash_pass; //"GwynethPaltrow28d36f3969e05dedb5f9ba20acd3842a";
S: pwd_bcrypted=bcrypt(new_pwd); //"$2a$04$qh7z5sSkMCrLq6mrpdOwM.ohlvCKWvU3vQm.CrjrxcQc6otwByBle"³
S>D: INSERT INTO users ('username','password') VALUES ('johndow','$2a$04$qh7z5sSkMCrLq6mrpdOwM.ohlvCKWvU3vQm.CrjrxcQc6otwByBle')


C>S: I want to sign in, send me the public pepper.
S>C: {"system_public_pepper":"Potts"}
U>C: {"username":"johndoe","password":"IWasBornOn1987"}
C: P=system_public_pepper+username+password; //P="PottsjohndowIWasBornOn1987"
C: H=md5(P); //="28d36f3969e05dedb5f9ba20acd3842a"²
C>S: {"username":"johndoe","hashpass":"28d36f3969e05dedb5f9ba20acd3842a"}
S: private_pepper="GwynethPaltrow";
S: attempt_pwd=private_pepper+hash_pass; //"GwynethPaltrow28d36f3969e05dedb5f9ba20acd3842a";
S>D: SELECT 'username', 'password' FROM users WHERE 'username'='johndoe'  //'$2a$04$qh7z5sSkMCrLq6mrpdOwM.ohlvCKWvU3vQm.CrjrxcQc6otwByBle'
S: password_verify(attempt_pwd,stored_hash)


  1. I know that it would be odd, since usually if you can sniff an HTTPS communication, you can also run a MitM attack. But I was thinking about a generic attack only aimed at reading because it may work on a massive amount of sites. While modifying them would require more work. So, at least I can prevent those. Also, I suppose it could be a specific attack to the OS or HTTPS deamon that allows to read communications.

  2. Here is the key, the user password does not leave the client. Let's say there is a bug at the server, and the received communications get logged: you can't get the password logged, just the hashed version.

  3. The stored hash is neither the original password, nor the received one.


1 Answer 1


I think the detailed approach you have given can work. To address your specific point:

  1. Rule of thumb: No md5 is never okay, for anything.
  2. I'm not sure what you mean but pretty sure that the answer is: No.
  3. The order doesn't really matter although your point is correct and you should probably add field separators instead of just concatenating.

I think proposing this kind of change requires a consideration of the attacker model. Your connection should be secured by TLS and all this becomes moot.

You can do more advanced things, they are great but work a little different. Maybe looking Password Authenticated Key Exchange (PAKE) will give you some inspiration.

  • 1
    $\begingroup$ I think you are misunderstanding the question. As far as I understand it, @ESL is specifically proposing to change the login procedure to include hashing on the client's side and then using this hash as the password in a regular plain password based authentication. $\endgroup$
    – Maeher
    Commented Feb 1, 2018 at 7:51
  • $\begingroup$ I think there is a misunderstanding: 1) The client does not need to send the unhashed password. To the servers eyes, the received password is the hashed one ALWAYS. $\endgroup$
    – ESL
    Commented Feb 14, 2018 at 13:07
  • $\begingroup$ 2) The client does not send "the hash that is stored on the server", because the server hashed again (with a more secure hash). $\endgroup$
    – ESL
    Commented Feb 14, 2018 at 13:08
  • $\begingroup$ About PAKE, I read something before asking this. It seems too complicated to implement on a simple web server. $\endgroup$
    – ESL
    Commented Feb 14, 2018 at 13:12
  • $\begingroup$ @ESL I've expanded my answer. $\endgroup$
    – Elias
    Commented Feb 14, 2018 at 13:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.