0
$\begingroup$

Let's say I wish to setup a classic username & password authentication strategy on a server. All communication is encrypted via TLS. But ideally, I still do not want the server to be able to read the passwords in plain-text, even temporarily. To that end the client could send the password that is hashed and salted with some key (for simplicity let's assume it's the username). Let's call this a derived password. The server would then in turn hash and salt the derived password using an algorithm like Bcrypt or PBKDF2 and store it for future requests.

So far none of this is novel and there are plenty of discussions about this topic. But what I cannot find in these discussions is how to perform server-side validation of the strength of the plain-text password in question? Any client-side strength validation can be bypassed, or a client application might have a bug that insufficiently validates the strength, hence, strength validation is ought to be done on the server. But at the same time I do not want the server to have access to the plain-text password.

So my question is, are those 2 requirements mutually exclusive, or is there some way to achieve both requirements? Could the strength validation be done based on the derived password? At the very least, is it possible to check the length of the plain-text password using the derived password to prevent registration with, say, empty password? Or do I, as a project owner, just have to accept that some users can bypass client-side validation and shoulder no responsibility if their accounts get compromised as a result of bypassing client-side strength validation?

I realize that one could employ a mixed strategy, where a password is sent from a client in plain-text form only during registration/password reset, and in salted, hashed form for any subsequent request. This is an improvement over sending password in plain-text all the time, but still does not satisfy the requirement of never exposing the plain-text password to the server.

$\endgroup$
3
$\begingroup$

You cannot realistically check the strength of any password that has already been hashed when sent to you. Hash functions are One Way Functions by design, meaning that you are not supposed to be able to reverse the hash and get any meaningful information about the input.

However, you could fairly easily verify that the password does not belong to a short list of common, weak passwords, such as the empty string "", "abc", "123", "password", etc. You do that simply by repeating the client side hashing procedure with these inputs server side, and check for equality. The length of the list of such weak password will be limited by performance constraints. Since the hash submitted by the client is salted, the server will have to build this list anew for each registration and password change.

Consequently, the bulk of the password sanity checks will have to be performed client side, provided that the password is only sent as a hash value.

Your idea about a hybrid registration scheme, where the password is sent as plain text to the server just for a quick checkup, is not ideal, as you already mentioned. To begin with, you do not gain much by having the client send a plain-text password, instead of a plain hash of the same password. Most of the sanity checks that benefit from having a plain text password, could easily be performed client side. The bulk of the server side testing should probably best be performed as a search in a database of hashes of common weak passwords (a Rainbow Table).

That said, not finding the hash in such a database table, is no guarantee that the password is strong enough. A long password that is the concatenation of three or four random words from a dictionary, might be easily spotted if you have access to the plain text password, but would probably not be an entry even in a reasonably large rainbow table.

$\endgroup$
1
  • $\begingroup$ "You do that simply by repeating the client side hashing procedure with these inputs server side, and check for equality." - I haven't thought of this approach, but now I see how it can be effectively used to prevent registration of passwords from a list of special cases (such as empty string). Thank you. $\endgroup$ Aug 27 '21 at 10:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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