We have a requirement for a security audit that our password policy must disallow the re-use of a previous password from the last 4 used passwords.

We can accomplish this fairly easily by making a call to the server to allow it to compare the password candidate against the database's previous password hashes, but that introduces some lag time in transit. Our managers have asked us to investigate if we can eliminate the delay by implementing a pure client-side solution.

Therefore, my question focuses purely on the feasibility of a safe client-side solution.

Assume that a MITM attacker has found some means to gain access to the payload via HTTPS or client-side application vulnerability.

The Process

The only process I have been able to devise would be to transmit the previous password hashes with their server-side salts to the client ahead of time.

The Risk

The requirement of needing to send the server-side hashes with the password hashes is what presents the inherent risk in my estimation.

Without the salt, then the client would be unable to test the candidate password against the password hashes. However, sending the server-side salt to the client-side exposes it to a potential MITM attacker.

If the attacker was successfully able to bruteforce the current password hash among the previous password hashes, then they could change the password under the nose of the current user.

This exploit could be exasperated if a user requested to change their password, was sent the previous password hashes + salt, and then chose to abandon the changing of the password. This would give a MITM attacker plenty of time to find a suitable entry for the current password hash + salt, and subsequently change the password.

Even if the attacker wasn't able to crack the current password in time, they'd still have plenty of time to crack and use these passwords on other sites where they may not have been updated.

The Question

I've been advised by peers that this might be overly cautious - that hashing functions like Bcrypt would take so long to bruteforce that it's practically impossible even with the salt exposed to the attacker...

In my estimation, this is equivalent to the result of a SQL injection attack. Nonetheless, I'm having trouble convincing my peers...

Is this method of checking if a password candidate would collide with a previous password unsafe? If so, is there another mechanism that would be safe, but which does not require remote calls to a server?

  • 2
    "Assume that a MITM attacker has found some means to gain access to the payload via HTTPS or client-side application vulnerability." Are you sure you want us to assume that? Because if that is the case, there is no security mechanism in the world that will protect you and your users. No need to mess with the hashes-- they could just sniff the user's chosen password.
    – John Wu
    Commented Feb 5, 2019 at 0:57
  • @JohnWu The password is hashed on the client, and then again on the server with salt. I've also argued this point with them too. In my opinion, I don't even see any point in hashing client-side, but my peers assure me there is benefit...what I've read seems pretty mixed on that point. I guess my point is that, there are many ways an attacker might manage to grab the previous password hashes as a MITM, not just HTTPS. I didn't want to get hung up on the details of how.
    – crush
    Commented Feb 5, 2019 at 3:21
  • There's a much bigger risk in this scenario: I strongly suspect most of your users are reusing their passwords as much as possible, so brute-forcing one of their old passwords means the attacker has brute-forced one of their future passwords.
    – Ed Grimm
    Commented Feb 5, 2019 at 6:38
  • Um... I just realized where this was after posting my last comment. Why isn't this on security SE? It would seem to me more on topic there. I would have thought that it would already have been a question there, but a quick search didn't find a duplicate.
    – Ed Grimm
    Commented Feb 5, 2019 at 6:55
  • 4
    My general impression is that your associates are a bit "old school." Forcing users to reset passwords and imposing other restrictions on them is part of an out of date philosophy known as fixing the user; it doesn't work; it is actually counterproductive. Don't fix the user. Fix your system. Open up the password rules, allow as many characters as they want, encourage them to use a password manager, and implement 2FA. NIST agrees,
    – John Wu
    Commented Feb 5, 2019 at 7:40

3 Answers 3


Secrets Are Not Shared

Unless they are not secrets

Ironically from a security perspective that delay, is actually a feature.

To a user, for the most part they will get it right, perhaps they will get it wrong once or twice, after that they'll usually call the help desk anyway. So generally speaking they will pay 1 to 4 times the delay, before they'll switch to the phenomenally slower telephone.

To an attacker they need to guess billions of times and get it wrong before chances start to favour them. Of course the favour is usually due to poor password selection in the first place - most people pick easy to guess passwords, or riff on a basic template by changing say a number on the end. But that aside an attacker using a pure brute-forcing on a 2^512 hash needs to request on average 2^256 checks.

By keeping the hash+salt on the server, each of those request must come to your server. This accomplishes two things:

  1. Your server acts as a bottle neck slowing the attack
  2. You can see from the logs that someone is attacking the account permitting defensive tactics like locking the account, or blocking the ip.

By giving the hash+salt to the client to compare themselves:

  1. The client (being compromised) can distribute those out to a cloud platform bringing parallel and optimised vector machines to bear on the hash.
  2. You cannot see if an attack is being mounted, the first sign you will see is a successful login - is it legitimate? This then brings in two tier auth and other problems, which will slow down authentication again.

What to do

If login/password change is slow, find ways to speed up the server for the first 3/4 attempts. Find the bottleneck and provide resources. After those first requests though specifically slow it down. Legitimate users will divert to the help desk.

Push back on the business and point out how "optimising" this process actually makes it insecure. Point out that it is the first step toward a massive data breach.

  • In my experience, letting the server do the password history check inline with changing the password is basically as fast as changing the password. We're talking mere microseconds worth of difference - at least on a server with overall good performance. Unless there's a problem with the server, or you're reusing passwords, you'll never notice the difference.
    – Ed Grimm
    Commented Feb 5, 2019 at 6:30

We have a requirement for a security audit that our password policy must disallow the re-use of a previous password from the last 4 used passwords.

"Four" sounds a little arbitrary, but anyway ...

We can accomplish this fairly easily by making a call to the server ... but that introduces some lag time in transit.

Really? A lag so long that it's considered a Performance Issue significant enough for you to spend time looking into it?

This delay will only be incurred when a User changes their Password. How often is that going to happen and how much of a delay, proportionally, might this introduce? Say it takes a whole second for each User, once every three months. What return on Investment are the Management expecting to see from this work?

This really does sound like a case of Premature Optimisation to me.

Our managers have asked us to investigate if we can eliminate the delay by implementing a pure client-side solution.

Basic Rule of Thumb: Nothing run on or coming from the Client can be trusted. Anything you write can, in theory at least, be circumvented.

Presumably this would be written in some client-side scripting language; all someone would have to do is comment out the call to the [well-written, nicely encapsulated] password checking function and they would be able to reuse the same password forever more - and you'd never know about it.

Secure stuff must be done in a secure environment and that's the Server that you have control over. Anything else is just smoke and mirrors.

  • 4 comes from the requirements for SOC2+HITRUST, and is a minimum requirement. The lag time is significant only in the context of giving immediate feedback to the user. Management claims it feels "delayed" compared to the rest of the inline password strength requirement checks which occur on every keystroke client-side...I agree. Seems nitpicky, and I think that the great advice here will help me put this issue to bed once and for all. Getting some more voices behind me will help.
    – crush
    Commented Feb 5, 2019 at 14:47
  • I found out that 4 actually comes from PCI DSS to which SOC2+HITRUST defers.
    – crush
    Commented Feb 5, 2019 at 17:39
  • They want to have the password history checked at every keystroke?! I think that sounds like they not only want to be able to reuse passwords every five changes, but they want a software assist to aid them in that effort.
    – Ed Grimm
    Commented Feb 5, 2019 at 22:45
  • @EdGrimm My management prefers the instant feedback, and they felt it was a strange user experience to get some feedback on every keystroke (entropy/strength), and some additional feedback every few seconds as the remote requests complete. Fortunately, with some of the perspectives provided on this Q&A, I've been able to convince them not to sacrifice security just to try and minimally improve user experience. As an aside, PCI DSS only requires checking against the last 4 passwords as a minimum; we can of course compare a longer history at our own discretion.
    – crush
    Commented Feb 7, 2019 at 17:55

There’s no reason to use the salt from the server, you might as well use a salt created on the client, and a good hash function on the client.

You just have to prepare for the incredibly unlikely case that a password passes the test on the client but not on the server, which will have different hash values.

Whether it’s better to have no client code but to do everything just on the server is another question.

  • This seems to be answering a different question. Or else has a severe misunderstanding of how hash functions and salts work.
    – 8bittree
    Commented Feb 5, 2019 at 20:05
  • It's answering the same question, it's just assuming that the person reading it realizes what is being intended. Specifically, gnasher729 is suggesting storing the passwords in a hash locally in addition to in the password database... But while that would technically work, it would probably violate other requirements. It at least violates the spirit of having the existing database be authoritative for passwords and provides another place where the hashed passwords can be acquired for brute-force cracking. And it's likely to be implemented much less securely than the intended repository.
    – Ed Grimm
    Commented Feb 5, 2019 at 22:37

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.