Several thousand characters (or worse, unlimited length) opens up your attack to a form of DDoS where you can exploit the fact that password hashing is a computationally heavy operation. See here: https://arstechnica.com/information-technology/2013/09/long-...
> Django does not impose any maximum on the length of the plaintext password, meaning that an attacker can simply submit arbitrarily large—and guaranteed-to-fail—passwords, forcing a server running Django to perform the resulting expensive hash computation in an attempt to check the password. A password one megabyte in size, for example, will require roughly one minute of computation to check when using the PBKDF2 hasher. This allows for denial-of-service attacks through repeated submission of large passwords, tying up server resources in the expensive computation of the corresponding hashes.
But instead of the server accepting an arbitrary string, it only accepts hexadecimal or base64 strings of a specific length. Which solves the problem.
If the client sends only a hex/base64 string, how can the server trust that it's the result of a password being fed to a KDF?
The threat model is: Password is too long, lots of CPU is wasted, denial of service.
By only accepting strings of a certain length, the threat is defeated.
The client could send an intentionally bad password even if they weren't lying. If they lie, only the client is harmed, and in a non-new way.
So this scheme has one notable upside, and no notable downside.
There are better solutions, but this one is valid.
Maybe it's just that it's not the norm, but I'm still unsure I'd actually use this scheme.
As the owner/maintainer of a service, I want to be in control and know that my user's credentials are secure - there may even be legal obligations here in some countries.
TBH, my preferred solution here is never to silently truncate passwords, and just to set a "sensible" limit on password length, e.g. 256 characters. Yes, it's still an arbitrary limit, but it should be long enough to cover 99.9999% of users.
The code doing the client-side hashing is just as secure as the rest of the client interface. You don't compromise anything by doing it.
Still, it's easier to do the extra hash locally on the server if you need it.
There's no need to have a cap bigger than a kilobyte though.
What you need is for the slow core of the algorithm to be fixed-speed.
Either by only reading the input bytes during initialization, or by only feeding a fixed number of input bytes into the core during each round.