I am in doubt whether to encrypt a password before sending it to the server, and on the server to save the hash to the database, or whether to encrypt only on the server ...
I am in doubt whether to encrypt a password before sending it to the server, and on the server to save the hash to the database, or whether to encrypt only on the server ...
There is a difference between encryption (protect communication between client-server, example of algorithms: AES, ChaCha20, Salsa20, DES, 3DES ...) and derive (prevent initial value discovery and conversion of passwords to keys , examples: PBKDF2, Bcrypt, Scrypt, Argon2).
There are advantages between deriving on the client side. One of them is to avoid DoS on your server, you did not read wrong.
What happens is that the Password Based Key Derivation Function (PBKDF) algorithms are extremely dependent on the computational cost, the more the better. An offline criptomoeda wallet can afford to take 10 seconds, using all processor cores and more than 8GB of RAM, just to derive a password. A password-based disk encryption (it first converts the password into a key, using such a derivation, to then encrypt) may also take a few minutes to derive, taking the device to the extreme, as this should only be done once.
However, websites can not afford this. Your website should respond quickly, usually in less than 1 second. It should still respond to multiple users. Therefore, you can not use 100% of the server capacity only for this activity, so you should reduce the computational difficulty.
So you can combine both sides. Your client is part of the job and you do the other part. Your client can use PBKDF2 (natively available in the WebCrypto API) and your server uses this result and derives with Argon2, so compare. It is important to note that your server should derive the derived result, if you are not storing a password equally in clear text.
The derivation requires a salt, which must be unique. In the case of the client, the salt may be the email, it will be unique, but deterministic, if the email is not changed. But if the password is changed it will use the same salt, so there will be two passwords for the same salt, which is not "perfect". The other way is to make a query of which user's salt, but this can also reveal whether it is registered or not. Another evil is users with slow computers, or smartphones, that may take longer to log in.
LastPass uses the technique of deriving on the client side.
Encrypting does not make much sense. TLS already does this, so just use HTTPS.
Encryption and hashing are different things. Usually when you havehing a password, you add "salts", which are extra items added to the password before making the hash for greater security.
For example you can save the user's password as data_cadastro + senha + id
and make a hash of it. When you validate the password, you get the registration date, id and concatenate with the password of the user who was informed, and compare the two hashes.
This provides an extra layer of security and no client knows what their hashing methods are.
If you do this on the front, it's easy for the customer to figure out how it's done.
I think you should stay in the same backend.
Remembering that over HTTPS, information is already sent to the encrypted server through SSL. If that was one of the reasons for questioning, HTTPS already covers;)