Para el hashing de contraseña, usualmente se usa bcrypt porque el tiempo requerido para calcular el hash se puede ajustar y bcrypt agrega automáticamente un salt aleatorio. Sin embargo, primero no estoy al tanto de una implementación de JavaScript de bcrypt, segundo, incluso esos hashes pueden ser atacados por ataques de adivinación estadística (intente primero con las contraseñas más comunes).
Pensé en el cifrado asimétrico aquí primero. Para cada inicio de sesión / registro, el servidor crea un par único de clave pública / privada y envía la clave pública al cliente. El cliente encripta la contraseña con esta clave. Solo el servidor que posee la clave privada puede descifrar la contraseña. Pero aún falta la autenticación. Un atacante podría escuchar la comunicación.
Sin la autenticación, que proporciona HTTPs, no es posible asegurar el paso de registro e inicio de sesión.