DEV Community

loading...

Discussion on: How to securely hash and store passwords in your next application

Collapse
dwd profile image
Dave Cridland

Encrypting on the client side leads to a subtle attack, actually - the encrypted password is now a "plaintext equivalent", and the temptation then on the serverside is to do a encrypted_password == stored_hash. And then the attacker can work through, byte by byte, with a timing attack and ultimately find the entire encrypted password.

Whoops.

This is because the typical string comparison code - such as the C library strcmp() call - works through byte by byte in a for loop and bails at the first mismatch. An attacker can time the rejections carefully, and slowly by surely increase the matches.

Yes, it's a slow method - but much faster than brute force, and surprisingly plausible.

As you've noted, libraries like the Python bcrypt provide a check function that - if you dig into the code - you'll probably find will take the same time on any failure or success. These are known as "constant time" functions, and they're useful things.

So, don't encrypt on the client-side - or rather, you can but you should always encrypt server-side as well.

Typically, though, we can trust TLS and skip doing much client-side. Indeed, if you're about to send over a plaintext equivalent - a stable, repeatable transformation of the original input password - there's little point worrying - if an attacker can see "inside" the TLS channel, they can just re-use the plaintext equivalent you're sending anyway.

But in some cases that's not a valid assumption. For example, some bizarre corporate security systems essentially MITM the TLS channel with a root certificate imposed on the client system. If this is within your threat model, look at the design of SCRAM, and use that - that uses a simple, hash-based, mechanism to encrypt and transfer a plaintext equivalent hash and then verify the server knew it, all without storing plaintext passwords (or password equivalents) on the server.

And, of course, also look at implementing TOTP and getting a cheap 2FA system up - whether or not you're worrying about plaintext equivalents.